Some updates

This commit is contained in:
WolverinDEV 2020-02-15 14:03:32 +01:00
parent 9e2249462c
commit 97fd71b69a
11 changed files with 5206 additions and 5206 deletions

View File

@ -1,286 +1,286 @@
cmake_minimum_required(VERSION 3.6) cmake_minimum_required(VERSION 3.6)
project(TeaSpeak-Shared) project(TeaSpeak-Shared)
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD 20)
if(NOT WIN32) if(NOT WIN32)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -Wall -Wno-reorder -Wno-sign-compare -fpermissive -ftemplate-depth=1000 ${MEMORY_DEBUG_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -Wall -Wno-reorder -Wno-sign-compare -fpermissive -ftemplate-depth=1000 ${MEMORY_DEBUG_FLAGS}")
set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_INCLUDE_CURRENT_DIR ON)
else() else()
#For Windows #For Windows
add_definitions(-D_SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING) add_definitions(-D_SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING)
add_compile_options(/wd4996) #'std::result_of_t': warning STL4014: std::result_of and std::result_of_t are deprecated in C++17. add_compile_options(/wd4996) #'std::result_of_t': warning STL4014: std::result_of and std::result_of_t are deprecated in C++17.
endif() endif()
if(CMAKE_PLATFORM_INCLUDE AND NOT CMAKE_PLATFORM_INCLUDE STREQUAL "") if(CMAKE_PLATFORM_INCLUDE AND NOT CMAKE_PLATFORM_INCLUDE STREQUAL "")
include(${CMAKE_PLATFORM_INCLUDE}) include(${CMAKE_PLATFORM_INCLUDE})
endif() endif()
find_package(TomMath REQUIRED) find_package(TomMath REQUIRED)
include_directories(${TomMath_INCLUDE_DIR}) include_directories(${TomMath_INCLUDE_DIR})
find_package(TomCrypt REQUIRED) find_package(TomCrypt REQUIRED)
include_directories(${TomCrypt_INCLUDE_DIR}) include_directories(${TomCrypt_INCLUDE_DIR})
find_package(DataPipes REQUIRED) find_package(DataPipes REQUIRED)
include_directories(${DataPipes_INCLUDE_DIR}) include_directories(${DataPipes_INCLUDE_DIR})
# LibEvent fucks up the CMAKE_FIND_LIBRARY_SUFFIXES variable # LibEvent fucks up the CMAKE_FIND_LIBRARY_SUFFIXES variable
if (NOT find_event) if (NOT find_event)
function(find_event static) function(find_event static)
if(static) if(static)
set(LIBEVENT_STATIC_LINK TRUE) set(LIBEVENT_STATIC_LINK TRUE)
endif() endif()
find_package(Libevent REQUIRED) find_package(Libevent REQUIRED)
include_directories(${LIBEVENT_INCLUDE_DIRS}) include_directories(${LIBEVENT_INCLUDE_DIRS})
endfunction() endfunction()
endif () endif ()
find_event(ON) find_event(ON)
find_package(StringVariable REQUIRED) find_package(StringVariable REQUIRED)
include_directories(${StringVariable_INCLUDE_DIR}) include_directories(${StringVariable_INCLUDE_DIR})
find_package(Ed25519 REQUIRED) find_package(Ed25519 REQUIRED)
include_directories(${ed25519_INCLUDE_DIR}) include_directories(${ed25519_INCLUDE_DIR})
find_package(ThreadPool REQUIRED) find_package(ThreadPool REQUIRED)
include_directories(${ThreadPool_INCLUDE_DIR}) include_directories(${ThreadPool_INCLUDE_DIR})
if(WIN32) if(WIN32)
add_definitions(-DWINDOWS) #Required for ThreadPool add_definitions(-DWINDOWS) #Required for ThreadPool
endif() endif()
find_package(spdlog REQUIRED) find_package(spdlog REQUIRED)
link_libraries(spdlog::spdlog_header_only) #Its a header only lib so we should be fine :) link_libraries(spdlog::spdlog_header_only) #Its a header only lib so we should be fine :)
if(NOT TEASPEAK_SERVER) if(NOT TEASPEAK_SERVER)
add_definitions(-DNO_OPEN_SSL) add_definitions(-DNO_OPEN_SSL)
add_definitions(-D_HAS_STD_BYTE) add_definitions(-D_HAS_STD_BYTE)
#FML #FML
else() else()
find_package(CXXTerminal REQUIRED) find_package(CXXTerminal REQUIRED)
add_definitions(-DHAVE_CXX_TERMINAL) add_definitions(-DHAVE_CXX_TERMINAL)
add_definitions(-DHAVE_JSON) add_definitions(-DHAVE_JSON)
set(HAVE_SQLITE3 ON) set(HAVE_SQLITE3 ON)
set(HAVE_OPEN_SSL ON) set(HAVE_OPEN_SSL ON)
message("HAVE JSON!") message("HAVE JSON!")
endif() endif()
if (MSVC) if (MSVC)
set(CompilerFlags set(CompilerFlags
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS
CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_DEBUG
CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELEASE
CMAKE_CXX_FLAGS_RELWITHDEBINFO CMAKE_CXX_FLAGS_RELWITHDEBINFO
CMAKE_C_FLAGS_RELWITHDEBINFO CMAKE_C_FLAGS_RELWITHDEBINFO
CMAKE_C_FLAGS CMAKE_C_FLAGS
CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_DEBUG
CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_RELEASE
) )
foreach(CompilerFlag ${CompilerFlags}) foreach(CompilerFlag ${CompilerFlags})
string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}") string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}")
endforeach() endforeach()
add_compile_options("/EHsc") #We require exception handling add_compile_options("/EHsc") #We require exception handling
else() else()
set(CMAKE_CXX_FLAGS_RELEASE "-O3") #-DNDEBUG We want assert! set(CMAKE_CXX_FLAGS_RELEASE "-O3") #-DNDEBUG We want assert!
endif() endif()
add_definitions(-DUSE_BORINGSSL) add_definitions(-DUSE_BORINGSSL)
include_directories(${LIBRARY_PATH}/boringssl/include/) include_directories(${LIBRARY_PATH}/boringssl/include/)
set(SOURCE_FILES set(SOURCE_FILES
src/misc/rnd.cpp src/misc/rnd.cpp
src/misc/time.cpp src/misc/time.cpp
src/misc/memtracker.cpp src/misc/memtracker.cpp
src/misc/digest.cpp src/misc/digest.cpp
src/misc/base64.cpp src/misc/base64.cpp
#Logger #Logger
src/log/LogUtils.cpp src/log/LogUtils.cpp
src/log/LogSinks.cpp src/log/LogSinks.cpp
src/qlz/QuickLZ.cpp src/qlz/QuickLZ.cpp
src/qlz/QuickLZ_L3.cpp src/qlz/QuickLZ_L3.cpp
src/qlz/QuickLZ_L1.cpp src/qlz/QuickLZ_L1.cpp
src/converters/converter.cpp src/converters/converter.cpp
src/query/command3.cpp src/query/command3.cpp
src/query/command2.cpp src/query/command2.cpp
src/query/Command.cpp src/query/Command.cpp
src/query/escape.cpp src/query/escape.cpp
src/protocol/generation.cpp src/protocol/generation.cpp
src/protocol/Packet.cpp src/protocol/Packet.cpp
src/protocol/buffers.cpp src/protocol/buffers.cpp
src/protocol/buffers_allocator_c.cpp src/protocol/buffers_allocator_c.cpp
src/PermissionManager.cpp src/PermissionManager.cpp
src/Properties.cpp src/Properties.cpp
src/BasicChannel.cpp src/BasicChannel.cpp
src/Error.cpp src/Error.cpp
src/protocol/CryptHandler.cpp src/protocol/CryptHandler.cpp
src/protocol/CompressionHandler.cpp src/protocol/CompressionHandler.cpp
src/Variable.cpp src/Variable.cpp
src/linked_helper.cpp src/linked_helper.cpp
src/EventLoop.cpp src/EventLoop.cpp
src/License.cpp src/License.cpp
src/bbcode/bbcodes.cpp src/bbcode/bbcodes.cpp
src/channel/TreeView.cpp src/channel/TreeView.cpp
src/protocol/ringbuffer.cpp src/protocol/ringbuffer.cpp
src/protocol/AcknowledgeManager.cpp src/protocol/AcknowledgeManager.cpp
) )
set(HEADER_FILES set(HEADER_FILES
src/misc/base64.h src/misc/base64.h
src/misc/endianness.h src/misc/endianness.h
src/misc/cast.h src/misc/cast.h
src/misc/rnd.h src/misc/rnd.h
src/misc/time.h src/misc/time.h
src/misc/std_unique_ptr.h src/misc/std_unique_ptr.h
src/misc/net.h src/misc/net.h
src/misc/lambda.h src/misc/lambda.h
src/misc/hex.h src/misc/hex.h
src/misc/advanced_mutex.h src/misc/advanced_mutex.h
src/misc/memtracker.h src/misc/memtracker.h
src/misc/strobf.h src/misc/strobf.h
src/log/translation.h src/log/translation.h
src/log/LogUtils.h src/log/LogUtils.h
src/PermissionManager.h src/PermissionManager.h
src/protocol/buffers.h src/protocol/buffers.h
src/protocol/Packet.h src/protocol/Packet.h
src/Properties.h src/Properties.h
src/BasicChannel.h src/BasicChannel.h
src/Definitions.h src/Definitions.h
src/Error.h src/Error.h
src/protocol/CryptHandler.h src/protocol/CryptHandler.h
src/Variable.h src/Variable.h
src/misc/queue.h src/misc/queue.h
src/misc/digest.h src/misc/digest.h
src/bbcode/bbcodes.h src/bbcode/bbcodes.h
src/channel/TreeView.h src/channel/TreeView.h
) )
if(HAVE_SQLITE3) if(HAVE_SQLITE3)
set(SOURCE_FILES ${SOURCE_FILES} set(SOURCE_FILES ${SOURCE_FILES}
src/sql/SqlQuery.cpp src/sql/SqlQuery.cpp
src/sql/sqlite/SqliteSQL.cpp src/sql/sqlite/SqliteSQL.cpp
src/sql/mysql/MySQL.cpp src/sql/mysql/MySQL.cpp
) )
set(HEADER_FILES ${HEADER_FILES} set(HEADER_FILES ${HEADER_FILES}
src/sql/SqlQuery.h src/sql/SqlQuery.h
src/sql/sqlite/SqliteSQL.h src/sql/sqlite/SqliteSQL.h
src/sql/mysql/MySQL.h src/sql/mysql/MySQL.h
) )
endif() endif()
if(HAVE_OPEN_SSL) if(HAVE_OPEN_SSL)
set(SOURCE_FILES ${SOURCE_FILES} set(SOURCE_FILES ${SOURCE_FILES}
src/ssl/SSLManager.cpp src/ssl/SSLManager.cpp
) )
set(HEADER_FILES ${HEADER_FILES} set(HEADER_FILES ${HEADER_FILES}
src/ssl/SSLManager.h src/ssl/SSLManager.h
) )
endif() endif()
add_library(TeaSpeak STATIC ${SOURCE_FILES} ${HEADER_FILES}) add_library(TeaSpeak STATIC ${SOURCE_FILES} ${HEADER_FILES})
target_link_libraries(TeaSpeak PUBLIC threadpool::static jsoncpp_lib) target_link_libraries(TeaSpeak PUBLIC threadpool::static jsoncpp_lib)
target_compile_options(TeaSpeak PRIVATE "-Wall") target_compile_options(TeaSpeak PRIVATE "-Wall")
if (TEASPEAK_SERVER) if (TEASPEAK_SERVER)
target_link_libraries(TeaSpeak PUBLIC CXXTerminal::static) target_link_libraries(TeaSpeak PUBLIC CXXTerminal::static)
endif () endif ()
target_include_directories(TeaSpeak PUBLIC src/) target_include_directories(TeaSpeak PUBLIC src/)
install(TARGETS TeaSpeak install(TARGETS TeaSpeak
ARCHIVE DESTINATION lib ARCHIVE DESTINATION lib
) )
INSTALL ( INSTALL (
DIRECTORY ${CMAKE_SOURCE_DIR}/src/ DIRECTORY ${CMAKE_SOURCE_DIR}/src/
DESTINATION include DESTINATION include
FILES_MATCHING PATTERN "*.h*" FILES_MATCHING PATTERN "*.h*"
) )
set(TEST_LIBRARIES set(TEST_LIBRARIES
threadpool::static #Static threadpool::static #Static
TeaSpeak #Static TeaSpeak #Static
TeaLicenseHelper #Static TeaLicenseHelper #Static
TeaMusic #Static TeaMusic #Static
CXXTerminal::static #Static CXXTerminal::static #Static
${StringVariable_LIBRARIES_STATIC} ${StringVariable_LIBRARIES_STATIC}
${YAML_CPP_LIBRARIES} ${YAML_CPP_LIBRARIES}
pthread pthread
stdc++fs stdc++fs
libevent::core libevent::pthreads libevent::core libevent::pthreads
opus::static opus::static
yaml-cpp yaml-cpp
${LIBRARY_PATH_PROTOBUF} ${LIBRARY_PATH_PROTOBUF}
#We're forsed to use boringssl caused by the fact that boringssl is already within webrtc! #We're forsed to use boringssl caused by the fact that boringssl is already within webrtc!
#Require a so #Require a so
sqlite3 sqlite3
breakpad::static breakpad::static
protobuf::libprotobuf protobuf::libprotobuf
jemalloc::shared jemalloc::shared
tomcrypt::static tomcrypt::static
tommath::static tommath::static
mysqlclient.a mysqlclient.a
jsoncpp_lib jsoncpp_lib
${ed25519_LIBRARIES_STATIC} ${ed25519_LIBRARIES_STATIC}
${DataPipes_LIBRARIES_SHARED} # Also includes glib2.0 ${DataPipes_LIBRARIES_SHARED} # Also includes glib2.0
openssl::ssl::shared openssl::ssl::shared
openssl::crypto::shared openssl::crypto::shared
dl dl
z z
) )
include_directories(src/) include_directories(src/)
option(BUILD_TESTS "Enable/disable test building" ON) option(BUILD_TESTS "Enable/disable test building" ON)
if(BUILD_TESTS) if(BUILD_TESTS)
add_executable(RingTest test/RingTest.cpp ${SOURCE_FILES}) add_executable(RingTest test/RingTest.cpp ${SOURCE_FILES})
target_link_libraries(RingTest ${TEST_LIBRARIES}) target_link_libraries(RingTest ${TEST_LIBRARIES})
if(NOT WIN32) if(NOT WIN32)
add_executable(CommandTest ${SOURCE_FILES} ${HEADER_FILES} test/CommandTest.cpp src/log/LogSinks.cpp src/log/LogSinks.h ../server/MySQLLibSSLFix.c) add_executable(CommandTest ${SOURCE_FILES} ${HEADER_FILES} test/CommandTest.cpp src/log/LogSinks.cpp src/log/LogSinks.h ../server/MySQLLibSSLFix.c)
target_link_libraries(CommandTest ${TEST_LIBRARIES}) target_link_libraries(CommandTest ${TEST_LIBRARIES})
add_executable(WebsocketTest ${SOURCE_FILES} ${HEADER_FILES} test/WSSTest.cpp src/log/LogSinks.cpp src/log/LogSinks.h) add_executable(WebsocketTest ${SOURCE_FILES} ${HEADER_FILES} test/WSSTest.cpp src/log/LogSinks.cpp src/log/LogSinks.h)
target_link_libraries(WebsocketTest ${TEST_LIBRARIES}) target_link_libraries(WebsocketTest ${TEST_LIBRARIES})
add_executable(SQLTest ${SOURCE_FILES} ${HEADER_FILES} test/SQLTest.cpp src/log/LogSinks.cpp src/log/LogSinks.h) add_executable(SQLTest ${SOURCE_FILES} ${HEADER_FILES} test/SQLTest.cpp src/log/LogSinks.cpp src/log/LogSinks.h)
target_link_libraries(SQLTest ${TEST_LIBRARIES}) target_link_libraries(SQLTest ${TEST_LIBRARIES})
add_executable(ChannelTest ${SOURCE_FILES} ${HEADER_FILES} test/ChannelTest.cpp src/log/LogSinks.cpp src/log/LogSinks.h) add_executable(ChannelTest ${SOURCE_FILES} ${HEADER_FILES} test/ChannelTest.cpp src/log/LogSinks.cpp src/log/LogSinks.h)
target_link_libraries(ChannelTest ${TEST_LIBRARIES}) target_link_libraries(ChannelTest ${TEST_LIBRARIES})
add_executable(EndianessTest ${SOURCE_FILES} ${HEADER_FILES} test/EndianessTest.cpp src/log/LogSinks.cpp src/log/LogSinks.h) add_executable(EndianessTest ${SOURCE_FILES} ${HEADER_FILES} test/EndianessTest.cpp src/log/LogSinks.cpp src/log/LogSinks.h)
target_link_libraries(EndianessTest ${TEST_LIBRARIES}) target_link_libraries(EndianessTest ${TEST_LIBRARIES})
include_directories(/usr/local/include/breakpad) include_directories(/usr/local/include/breakpad)
add_executable(CrashTest test/CrashTest.cpp ${SOURCE_FILES}) add_executable(CrashTest test/CrashTest.cpp ${SOURCE_FILES})
target_link_libraries(CrashTest ${TEST_LIBRARIES}) target_link_libraries(CrashTest ${TEST_LIBRARIES})
add_executable(PorpertyTest test/PropertyTest.cpp ${SOURCE_FILES}) add_executable(PorpertyTest test/PropertyTest.cpp ${SOURCE_FILES})
target_link_libraries(PorpertyTest ${TEST_LIBRARIES}) target_link_libraries(PorpertyTest ${TEST_LIBRARIES})
add_executable(BBTest test/BBTest.cpp ${SOURCE_FILES} src/query/command_unused.h) add_executable(BBTest test/BBTest.cpp ${SOURCE_FILES} src/query/command_unused.h)
target_link_libraries(BBTest ${TEST_LIBRARIES}) target_link_libraries(BBTest ${TEST_LIBRARIES})
add_executable(LinkedTest test/LinkedTest.cpp ${SOURCE_FILES}) add_executable(LinkedTest test/LinkedTest.cpp ${SOURCE_FILES})
target_link_libraries(LinkedTest ${TEST_LIBRARIES}) target_link_libraries(LinkedTest ${TEST_LIBRARIES})
add_executable(PermissionTest test/PermissionTest.cpp ${SOURCE_FILES}) add_executable(PermissionTest test/PermissionTest.cpp ${SOURCE_FILES})
target_link_libraries(PermissionTest ${TEST_LIBRARIES}) target_link_libraries(PermissionTest ${TEST_LIBRARIES})
add_executable(GenerationTest test/generationTest.cpp ${SOURCE_FILES} ../server/MySQLLibSSLFix.c) add_executable(GenerationTest test/generationTest.cpp ${SOURCE_FILES} ../server/MySQLLibSSLFix.c)
target_link_libraries(GenerationTest ${TEST_LIBRARIES}) target_link_libraries(GenerationTest ${TEST_LIBRARIES})
endif() endif()
endif() endif()

View File

@ -1,207 +1,207 @@
// //
// Created by wolverindev on 17.10.17. // Created by wolverindev on 17.10.17.
// //
#include "Error.h" #include "Error.h"
using namespace ts; using namespace ts;
const std::vector<ErrorType> ts::avariableErrors = { const std::vector<ErrorType> ts::avariableErrors = {
{0x0000, "ok" , "ok" }, {0x0000, "ok" , "ok" },
{0x0001, "undefined" , "undefined error" }, {0x0001, "undefined" , "undefined error" },
{0x0002, "not_implemented" , "not implemented" }, {0x0002, "not_implemented" , "not implemented" },
{0x0005, "lib_time_limit_reached" , "library time limit reached" }, {0x0005, "lib_time_limit_reached" , "library time limit reached" },
{0x0100, "command_not_found" , "command not found" }, {0x0100, "command_not_found" , "command not found" },
{0x0101, "unable_to_bind_network_port" , "unable to bind network port" }, {0x0101, "unable_to_bind_network_port" , "unable to bind network port" },
{0x0102, "no_network_port_available" , "no network port available" }, {0x0102, "no_network_port_available" , "no network port available" },
{0x0200, "client_invalid_id" , "invalid clientID" }, {0x0200, "client_invalid_id" , "invalid clientID" },
{0x0201, "client_nickname_inuse" , "nickname is already in use" }, {0x0201, "client_nickname_inuse" , "nickname is already in use" },
{0x0202, "" , "invalid error code" }, {0x0202, "" , "invalid error code" },
{0x0203, "client_protocol_limit_reached" , "max clients protocol limit reached" }, {0x0203, "client_protocol_limit_reached" , "max clients protocol limit reached" },
{0x0204, "client_invalid_type" , "invalid client type" }, {0x0204, "client_invalid_type" , "invalid client type" },
{0x0205, "client_already_subscribed" , "already subscribed" }, {0x0205, "client_already_subscribed" , "already subscribed" },
{0x0206, "client_not_logged_in" , "not logged in" }, {0x0206, "client_not_logged_in" , "not logged in" },
{0x0207, "client_could_not_validate_identity" , "could not validate client identity" }, {0x0207, "client_could_not_validate_identity" , "could not validate client identity" },
{0x0208, "client_invalid_password" , "invalid loginname or password" }, {0x0208, "client_invalid_password" , "invalid loginname or password" },
{0x0209, "client_too_many_clones_connected" , "too many clones already connected" }, {0x0209, "client_too_many_clones_connected" , "too many clones already connected" },
{0x020A, "client_version_outdated" , "client version outdated, please update" }, {0x020A, "client_version_outdated" , "client version outdated, please update" },
{0x020B, "client_is_online" , "client is online" }, {0x020B, "client_is_online" , "client is online" },
{0x020C, "client_is_flooding" , "client is flooding" }, {0x020C, "client_is_flooding" , "client is flooding" },
{0x020D, "client_hacked" , "client is modified" }, {0x020D, "client_hacked" , "client is modified" },
{0x020E, "client_cannot_verify_now" , "can not verify client at this moment" }, {0x020E, "client_cannot_verify_now" , "can not verify client at this moment" },
{0x020F, "client_login_not_permitted" , "client is not permitted to log in" }, {0x020F, "client_login_not_permitted" , "client is not permitted to log in" },
{0x0210, "client_not_subscribed" , "client is not subscribed to the channel" }, {0x0210, "client_not_subscribed" , "client is not subscribed to the channel" },
{0x0211, "client_unknown" , "client is not known" }, {0x0211, "client_unknown" , "client is not known" },
{0x0212, "client_join_rate_limit_reached" , "client has reached his join attempt limit" }, {0x0212, "client_join_rate_limit_reached" , "client has reached his join attempt limit" },
{0x0213, "client_is_already_member_of_group" , "client is already a member of the group" }, {0x0213, "client_is_already_member_of_group" , "client is already a member of the group" },
{0x0214, "client_is_not_member_of_group" , "client is not a member of the group" }, {0x0214, "client_is_not_member_of_group" , "client is not a member of the group" },
{0x0215, "client_type_is_not_allowed" , "client type is not allowed to join the server" }, {0x0215, "client_type_is_not_allowed" , "client type is not allowed to join the server" },
{0x0300, "channel_invalid_id" , "invalid channelID" }, {0x0300, "channel_invalid_id" , "invalid channelID" },
{0x0301, "channel_protocol_limit_reached" , "max channels protocol limit reached" }, {0x0301, "channel_protocol_limit_reached" , "max channels protocol limit reached" },
{0x0302, "channel_already_in" , "already member of channel" }, {0x0302, "channel_already_in" , "already member of channel" },
{0x0303, "channel_name_inuse" , "channel name is already in use" }, {0x0303, "channel_name_inuse" , "channel name is already in use" },
{0x0304, "channel_not_empty" , "channel not empty" }, {0x0304, "channel_not_empty" , "channel not empty" },
{0x0305, "channel_can_not_delete_default" , "can not delete default channel" }, {0x0305, "channel_can_not_delete_default" , "can not delete default channel" },
{0x0306, "channel_default_require_permanent" , "default channel requires permanent" }, {0x0306, "channel_default_require_permanent" , "default channel requires permanent" },
{0x0307, "channel_invalid_flags" , "invalid channel flags" }, {0x0307, "channel_invalid_flags" , "invalid channel flags" },
{0x0308, "channel_parent_not_permanent" , "permanent channel can not be child of non permanent channel"}, {0x0308, "channel_parent_not_permanent" , "permanent channel can not be child of non permanent channel"},
{0x0309, "channel_maxclients_reached" , "channel maxclient reached" }, {0x0309, "channel_maxclients_reached" , "channel maxclient reached" },
{0x030A, "channel_maxfamily_reached" , "channel maxfamily reached" }, {0x030A, "channel_maxfamily_reached" , "channel maxfamily reached" },
{0x030B, "channel_invalid_order" , "invalid channel order" }, {0x030B, "channel_invalid_order" , "invalid channel order" },
{0x030C, "channel_no_filetransfer_supported" , "channel does not support filetransfers" }, {0x030C, "channel_no_filetransfer_supported" , "channel does not support filetransfers" },
{0x030D, "channel_invalid_password" , "invalid channel password" }, {0x030D, "channel_invalid_password" , "invalid channel password" },
{0x030E, "channel_is_private_channel" , "channel is private channel" }, {0x030E, "channel_is_private_channel" , "channel is private channel" },
{0x030F, "channel_invalid_security_hash" , "invalid security hash supplied by client" }, {0x030F, "channel_invalid_security_hash" , "invalid security hash supplied by client" },
{0x0310, "channel_is_deleted" , "target channel is deleted" }, {0x0310, "channel_is_deleted" , "target channel is deleted" },
{0x0311, "channel_name_invalid" , "channel name is invalid" }, {0x0311, "channel_name_invalid" , "channel name is invalid" },
{0x0312, "channel_limit_reached" , "the virtualserver channel limit has been reached" }, {0x0312, "channel_limit_reached" , "the virtualserver channel limit has been reached" },
{0x0400, "server_invalid_id" , "invalid serverID" }, {0x0400, "server_invalid_id" , "invalid serverID" },
{0x0401, "server_running" , "server is running" }, {0x0401, "server_running" , "server is running" },
{0x0402, "server_is_shutting_down" , "server is shutting down" }, {0x0402, "server_is_shutting_down" , "server is shutting down" },
{0x0403, "server_maxclients_reached" , "server maxclient reached" }, {0x0403, "server_maxclients_reached" , "server maxclient reached" },
{0x0404, "server_invalid_password" , "invalid server password" }, {0x0404, "server_invalid_password" , "invalid server password" },
{0x0405, "server_deployment_active" , "deployment active" }, {0x0405, "server_deployment_active" , "deployment active" },
{0x0406, "server_unable_to_stop_own_server" , "unable to stop own server in your connection class" }, {0x0406, "server_unable_to_stop_own_server" , "unable to stop own server in your connection class" },
{0x0407, "server_is_virtual" , "server is virtual" }, {0x0407, "server_is_virtual" , "server is virtual" },
{0x0408, "server_wrong_machineid" , "server wrong machineID" }, {0x0408, "server_wrong_machineid" , "server wrong machineID" },
{0x0409, "server_is_not_running" , "server is not running" }, {0x0409, "server_is_not_running" , "server is not running" },
{0x040A, "server_is_booting" , "server is booting up" }, {0x040A, "server_is_booting" , "server is booting up" },
{0x040B, "server_status_invalid" , "server got an invalid status for this operation" }, {0x040B, "server_status_invalid" , "server got an invalid status for this operation" },
{0x040C, "server_modal_quit" , "server modal quit" }, {0x040C, "server_modal_quit" , "server modal quit" },
{0x040D, "server_version_outdated" , "server version is too old for command" }, {0x040D, "server_version_outdated" , "server version is too old for command" },
{0x040D, "server_already_joined" , "query client already joined to the server" }, {0x040D, "server_already_joined" , "query client already joined to the server" },
{0x040E, "server_is_not_shutting_down" , "server isn't shutting down" }, {0x040E, "server_is_not_shutting_down" , "server isn't shutting down" },
{0x040F, "server_max_vs_reached" , "You reached the maximal virtual server limit" }, {0x040F, "server_max_vs_reached" , "You reached the maximal virtual server limit" },
{0x0410, "server_unbound" , "you are not bound to any server" }, {0x0410, "server_unbound" , "you are not bound to any server" },
{0x0411, "server_join_rate_limit_reached" , "the server reached his join attempt limit" }, {0x0411, "server_join_rate_limit_reached" , "the server reached his join attempt limit" },
{0x0500, "sql" , "sql error" }, {0x0500, "sql" , "sql error" },
{0x0501, "database_empty_result" , "sql empty result set" }, {0x0501, "database_empty_result" , "sql empty result set" },
{0x0502, "database_duplicate_entry" , "sql duplicate entry" }, {0x0502, "database_duplicate_entry" , "sql duplicate entry" },
{0x0503, "database_no_modifications" , "sql no modifications" }, {0x0503, "database_no_modifications" , "sql no modifications" },
{0x0504, "database_constraint" , "sql invalid constraint" }, {0x0504, "database_constraint" , "sql invalid constraint" },
{0x0505, "database_reinvoke" , "sql reinvoke command" }, {0x0505, "database_reinvoke" , "sql reinvoke command" },
{0x0600, "parameter_quote" , "invalid quote" }, {0x0600, "parameter_quote" , "invalid quote" },
{0x0601, "parameter_invalid_count" , "invalid parameter count" }, {0x0601, "parameter_invalid_count" , "invalid parameter count" },
{0x0602, "parameter_invalid" , "invalid parameter" }, {0x0602, "parameter_invalid" , "invalid parameter" },
{0x0603, "parameter_not_found" , "parameter not found" }, {0x0603, "parameter_not_found" , "parameter not found" },
{0x0604, "parameter_convert" , "convert error" }, {0x0604, "parameter_convert" , "convert error" },
{0x0605, "parameter_invalid_size" , "invalid parameter size" }, {0x0605, "parameter_invalid_size" , "invalid parameter size" },
{0x0606, "parameter_missing" , "missing required parameter" }, {0x0606, "parameter_missing" , "missing required parameter" },
{0x0607, "parameter_checksum" , "invalid checksum" }, {0x0607, "parameter_checksum" , "invalid checksum" },
{0x0700, "vs_critical" , "virtual server got a critical error" }, {0x0700, "vs_critical" , "virtual server got a critical error" },
{0x0701, "connection_lost" , "Connection lost" }, {0x0701, "connection_lost" , "Connection lost" },
{0x0702, "not_connected" , "not connected" }, {0x0702, "not_connected" , "not connected" },
{0x0703, "no_cached_connection_info" , "no cached connection info" }, {0x0703, "no_cached_connection_info" , "no cached connection info" },
{0x0704, "currently_not_possible" , "currently not possible" }, {0x0704, "currently_not_possible" , "currently not possible" },
{0x0705, "failed_connection_initialisation" , "failed connection initialization" }, {0x0705, "failed_connection_initialisation" , "failed connection initialization" },
{0x0706, "could_not_resolve_hostname" , "could not resolve hostname" }, {0x0706, "could_not_resolve_hostname" , "could not resolve hostname" },
{0x0707, "invalid_server_connection_handler_id" , "invalid server connection handler ID" }, {0x0707, "invalid_server_connection_handler_id" , "invalid server connection handler ID" },
{0x0708, "could_not_initialise_input_client" , "could not initialize Input client" }, {0x0708, "could_not_initialise_input_client" , "could not initialize Input client" },
{0x0709, "clientlibrary_not_initialised" , "client library not initialized" }, {0x0709, "clientlibrary_not_initialised" , "client library not initialized" },
{0x070A, "serverlibrary_not_initialised" , "server library not initialized" }, {0x070A, "serverlibrary_not_initialised" , "server library not initialized" },
{0x070B, "whisper_too_many_targets" , "too many whisper targets" }, {0x070B, "whisper_too_many_targets" , "too many whisper targets" },
{0x070C, "whisper_no_targets" , "no whisper targets found" }, {0x070C, "whisper_no_targets" , "no whisper targets found" },
{0x0800, "file_invalid_name" , "invalid file name" }, {0x0800, "file_invalid_name" , "invalid file name" },
{0x0801, "file_invalid_permissions" , "invalid file permissions" }, {0x0801, "file_invalid_permissions" , "invalid file permissions" },
{0x0802, "file_already_exists" , "file already exists" }, {0x0802, "file_already_exists" , "file already exists" },
{0x0803, "file_not_found" , "file not found" }, {0x0803, "file_not_found" , "file not found" },
{0x0804, "file_io_error" , "file input/output error" }, {0x0804, "file_io_error" , "file input/output error" },
{0x0805, "file_invalid_transfer_id" , "invalid file transfer ID" }, {0x0805, "file_invalid_transfer_id" , "invalid file transfer ID" },
{0x0806, "file_invalid_path" , "invalid file path" }, {0x0806, "file_invalid_path" , "invalid file path" },
{0x0807, "file_no_files_available" , "no files available" }, {0x0807, "file_no_files_available" , "no files available" },
{0x0808, "file_overwrite_excludes_resume" , "overwrite excludes resume" }, {0x0808, "file_overwrite_excludes_resume" , "overwrite excludes resume" },
{0x0809, "file_invalid_size" , "invalid file size" }, {0x0809, "file_invalid_size" , "invalid file size" },
{0x080A, "file_already_in_use" , "file already in use" }, {0x080A, "file_already_in_use" , "file already in use" },
{0x080B, "file_could_not_open_connection" , "could not open file transfer connection" }, {0x080B, "file_could_not_open_connection" , "could not open file transfer connection" },
{0x080C, "file_no_space_left_on_device" , "no space left on device (disk full?)" }, {0x080C, "file_no_space_left_on_device" , "no space left on device (disk full?)" },
{0x080D, "file_exceeds_file_system_maximum_size", "file exceeds file system's maximum file size" }, {0x080D, "file_exceeds_file_system_maximum_size", "file exceeds file system's maximum file size" },
{0x080E, "file_transfer_connection_timeout" , "file transfer connection timeout" }, {0x080E, "file_transfer_connection_timeout" , "file transfer connection timeout" },
{0x080F, "file_connection_lost" , "lost file transfer connection" }, {0x080F, "file_connection_lost" , "lost file transfer connection" },
{0x0810, "file_exceeds_supplied_size" , "file exceeds supplied file size" }, {0x0810, "file_exceeds_supplied_size" , "file exceeds supplied file size" },
{0x0811, "file_transfer_complete" , "file transfer complete" }, {0x0811, "file_transfer_complete" , "file transfer complete" },
{0x0812, "file_transfer_canceled" , "file transfer canceled" }, {0x0812, "file_transfer_canceled" , "file transfer canceled" },
{0x0813, "file_transfer_interrupted" , "file transfer interrupted" }, {0x0813, "file_transfer_interrupted" , "file transfer interrupted" },
{0x0814, "file_transfer_server_quota_exceeded" , "file transfer server quota exceeded" }, {0x0814, "file_transfer_server_quota_exceeded" , "file transfer server quota exceeded" },
{0x0815, "file_transfer_client_quota_exceeded" , "file transfer client quota exceeded" }, {0x0815, "file_transfer_client_quota_exceeded" , "file transfer client quota exceeded" },
{0x0816, "file_transfer_reset" , "file transfer reset" }, {0x0816, "file_transfer_reset" , "file transfer reset" },
{0x0817, "file_transfer_limit_reached" , "file transfer limit reached" }, {0x0817, "file_transfer_limit_reached" , "file transfer limit reached" },
{0x0A08, "server_insufficeient_permissions" , "insufficient client permissions" }, {0x0A08, "server_insufficeient_permissions" , "insufficient client permissions" },
{0x0B01, "accounting_slot_limit_reached" , "max slot limit reached" }, {0x0B01, "accounting_slot_limit_reached" , "max slot limit reached" },
{0x0D01, "server_connect_banned" , "connection failed, you are banned" }, {0x0D01, "server_connect_banned" , "connection failed, you are banned" },
{0x0D03, "ban_flooding" , "flood ban" }, {0x0D03, "ban_flooding" , "flood ban" },
{0x0F00, "token_invalid_id" , "invalid privilege key" }, {0x0F00, "token_invalid_id" , "invalid privilege key" },
{0x1001, "web_handshake_invalid" , "Invalid handshake" }, {0x1001, "web_handshake_invalid" , "Invalid handshake" },
{0x1001, "web_handshake_unsupported" , "Handshake intention unsupported" }, {0x1001, "web_handshake_unsupported" , "Handshake intention unsupported" },
{0x1002, "web_handshake_identity_unsupported" , "Handshake identity unsupported" }, {0x1002, "web_handshake_identity_unsupported" , "Handshake identity unsupported" },
{0x1003, "web_handshake_identity_proof_failed" , "Identity proof failed" }, {0x1003, "web_handshake_identity_proof_failed" , "Identity proof failed" },
{0x1004, "web_handshake_identity_outdated" , "data seems to be outdated" }, {0x1004, "web_handshake_identity_outdated" , "data seems to be outdated" },
{0x1100, "music_invalid_id" , "invalid botID" }, {0x1100, "music_invalid_id" , "invalid botID" },
{0x1101, "music_limit_reached" , "Server music bot limit is reached" }, {0x1101, "music_limit_reached" , "Server music bot limit is reached" },
{0x1102, "music_client_limit_reached" , "Client music bot limit is reached" }, {0x1102, "music_client_limit_reached" , "Client music bot limit is reached" },
{0x1103, "music_invalid_player_state" , "Invalid player state" }, {0x1103, "music_invalid_player_state" , "Invalid player state" },
{0x1104, "music_invalid_action" , "Invalid action" }, {0x1104, "music_invalid_action" , "Invalid action" },
{0x1105, "music_no_player" , "Missing player instance" }, {0x1105, "music_no_player" , "Missing player instance" },
{0x1105, "music_disabled" , "Music bots have been disabled" }, {0x1105, "music_disabled" , "Music bots have been disabled" },
{0x2100, "playlist_invalid_id" , "invalid playlist id" }, {0x2100, "playlist_invalid_id" , "invalid playlist id" },
{0x2101, "playlist_invalid_song_id" , "invalid playlist song id" }, {0x2101, "playlist_invalid_song_id" , "invalid playlist song id" },
{0x2102, "playlist_already_in_use" , "playlist is already used by another bot" }, {0x2102, "playlist_already_in_use" , "playlist is already used by another bot" },
{0x2103, "playlist_is_in_use" , "playlist is used by another bot" }, {0x2103, "playlist_is_in_use" , "playlist is used by another bot" },
{0x2200, "conversation_invalid_id" , "invalid conversation id" }, {0x2200, "conversation_invalid_id" , "invalid conversation id" },
{0x2201, "conversation_more_data" , "there are more messages to send" }, {0x2201, "conversation_more_data" , "there are more messages to send" },
{0x2202, "conversation_is_private" , "the target conversation is private" }, {0x2202, "conversation_is_private" , "the target conversation is private" },
{0x1200, "query_not_exists" , "query account does not exists" }, {0x1200, "query_not_exists" , "query account does not exists" },
{0x1201, "query_already_exists" , "query account already exists" }, {0x1201, "query_already_exists" , "query account already exists" },
{0x1202, "query_too_many_simultaneously_sessions", "too many simultaneously connected sessions" }, {0x1202, "query_too_many_simultaneously_sessions", "too many simultaneously connected sessions" },
{0x1203, "query_maxclients_reached" , "query server reached its limit" }, {0x1203, "query_maxclients_reached" , "query server reached its limit" },
{0x1300, "group_invalid_id" , "Invalid group id" }, {0x1300, "group_invalid_id" , "Invalid group id" },
{0x1301, "group_name_inuse" , "Group name is already in use" }, {0x1301, "group_name_inuse" , "Group name is already in use" },
{0x1302, "group_not_assigned_over_this_server" , "the group hasn't been assigned over this server" }, {0x1302, "group_not_assigned_over_this_server" , "the group hasn't been assigned over this server" },
{0xE000, "resource_limit_reached" , "resource limit reached" }, {0xE000, "resource_limit_reached" , "resource limit reached" },
{0xFFFF, "custom_error" , "costume" }, {0xFFFF, "custom_error" , "costume" },
}; };
ErrorType ErrorType::Success = avariableErrors[0]; ErrorType ErrorType::Success = avariableErrors[0];
ErrorType ErrorType::Costume = findError("custom_error"); ErrorType ErrorType::Costume = findError("custom_error");
ErrorType ErrorType::VSError = findError("vs_critical"); ErrorType ErrorType::VSError = findError("vs_critical");
ErrorType ErrorType::DBEmpty = findError("database_empty_result"); ErrorType ErrorType::DBEmpty = findError("database_empty_result");
ErrorType ts::findError(uint16_t errorId){ ErrorType ts::findError(uint16_t errorId){
for(auto elm : avariableErrors) for(auto elm : avariableErrors)
if(elm.errorId == errorId) return elm; if(elm.errorId == errorId) return elm;
return ErrorType{errorId, "undefined", "undefined"}; return ErrorType{errorId, "undefined", "undefined"};
} }
ErrorType ts::findError(std::string key){ ErrorType ts::findError(std::string key){
for(auto elm : avariableErrors) for(auto elm : avariableErrors)
if(elm.name == key) return elm; if(elm.name == key) return elm;
return ErrorType{1, key, "undefined"}; return ErrorType{1, key, "undefined"};
} }
CommandResult CommandResult::Success = {avariableErrors[0], ""}; CommandResult CommandResult::Success = {avariableErrors[0], ""};
CommandResult CommandResult::NotImplemented = {avariableErrors[2], ""}; CommandResult CommandResult::NotImplemented = {avariableErrors[2], ""};
CommandResultPermissionError::CommandResultPermissionError(permission::PermissionType error, const std::string &extraMsg) : CommandResult(findError(0x0A08), "") { CommandResultPermissionError::CommandResultPermissionError(permission::PermissionType error, const std::string &extraMsg) : CommandResult(findError(0x0A08), "") {
this->extraProperties["failed_permid"] = std::to_string((int16_t) error); this->extraProperties["failed_permid"] = std::to_string((int16_t) error);
this->_type = PERM_ERROR; this->_type = PERM_ERROR;
} }

View File

@ -1,396 +1,396 @@
#pragma once #pragma once
#include <utility> #include <utility>
#include <memory> #include <memory>
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
#include <cstdint> #include <cstdint>
#include <string> #include <string>
#include <utility> #include <utility>
#include <vector> #include <vector>
#include <map> #include <map>
#define _NDEBUG #define _NDEBUG
namespace ts { namespace ts {
struct CommandResult; struct CommandResult;
namespace permission { namespace permission {
enum PermissionType : uint16_t; enum PermissionType : uint16_t;
} }
struct error { struct error {
enum type : uint16_t { enum type : uint16_t {
ok = 0x0, ok = 0x0,
undefined = 0x1, undefined = 0x1,
not_implemented = 0x2, not_implemented = 0x2,
lib_time_limit_reached = 0x5, lib_time_limit_reached = 0x5,
command_not_found = 0x100, command_not_found = 0x100,
unable_to_bind_network_port = 0x101, unable_to_bind_network_port = 0x101,
no_network_port_available = 0x102, no_network_port_available = 0x102,
client_invalid_id = 0x200, client_invalid_id = 0x200,
client_nickname_inuse = 0x201, client_nickname_inuse = 0x201,
invalid_error_code = 0x202, invalid_error_code = 0x202,
client_protocol_limit_reached = 0x203, client_protocol_limit_reached = 0x203,
client_invalid_type = 0x204, client_invalid_type = 0x204,
client_already_subscribed = 0x205, client_already_subscribed = 0x205,
client_not_logged_in = 0x206, client_not_logged_in = 0x206,
client_could_not_validate_identity = 0x207, client_could_not_validate_identity = 0x207,
client_invalid_password = 0x208, client_invalid_password = 0x208,
client_too_many_clones_connected = 0x209, client_too_many_clones_connected = 0x209,
client_version_outdated = 0x20a, client_version_outdated = 0x20a,
client_is_online = 0x20b, client_is_online = 0x20b,
client_is_flooding = 0x20c, client_is_flooding = 0x20c,
client_hacked = 0x20d, client_hacked = 0x20d,
client_cannot_verify_now = 0x20e, client_cannot_verify_now = 0x20e,
client_login_not_permitted = 0x20f, client_login_not_permitted = 0x20f,
client_not_subscribed = 0x210, client_not_subscribed = 0x210,
client_unknown = 0x0211, client_unknown = 0x0211,
client_join_rate_limit_reached = 0x0212, client_join_rate_limit_reached = 0x0212,
client_is_already_member_of_group = 0x0213, client_is_already_member_of_group = 0x0213,
client_is_not_member_of_group = 0x0214, client_is_not_member_of_group = 0x0214,
client_type_is_not_allowed = 0x0215, client_type_is_not_allowed = 0x0215,
channel_invalid_id = 0x300, channel_invalid_id = 0x300,
channel_protocol_limit_reached = 0x301, channel_protocol_limit_reached = 0x301,
channel_already_in = 0x302, channel_already_in = 0x302,
channel_name_inuse = 0x303, channel_name_inuse = 0x303,
channel_not_empty = 0x304, channel_not_empty = 0x304,
channel_can_not_delete_default = 0x305, channel_can_not_delete_default = 0x305,
channel_default_require_permanent = 0x306, channel_default_require_permanent = 0x306,
channel_invalid_flags = 0x307, channel_invalid_flags = 0x307,
channel_parent_not_permanent = 0x308, channel_parent_not_permanent = 0x308,
channel_maxclients_reached = 0x309, channel_maxclients_reached = 0x309,
channel_maxfamily_reached = 0x30a, channel_maxfamily_reached = 0x30a,
channel_invalid_order = 0x30b, channel_invalid_order = 0x30b,
channel_no_filetransfer_supported = 0x30c, channel_no_filetransfer_supported = 0x30c,
channel_invalid_password = 0x30d, channel_invalid_password = 0x30d,
channel_is_private_channel = 0x30e, channel_is_private_channel = 0x30e,
channel_invalid_security_hash = 0x30f, channel_invalid_security_hash = 0x30f,
channel_is_deleted = 0x310, channel_is_deleted = 0x310,
channel_name_invalid = 0x311, channel_name_invalid = 0x311,
channel_limit_reached = 0x312, channel_limit_reached = 0x312,
server_invalid_id = 0x400, server_invalid_id = 0x400,
server_running = 0x401, server_running = 0x401,
server_is_shutting_down = 0x402, server_is_shutting_down = 0x402,
server_maxclients_reached = 0x403, server_maxclients_reached = 0x403,
server_invalid_password = 0x404, server_invalid_password = 0x404,
server_deployment_active = 0x405, server_deployment_active = 0x405,
server_unable_to_stop_own_server = 0x406, server_unable_to_stop_own_server = 0x406,
server_is_virtual = 0x407, server_is_virtual = 0x407,
server_wrong_machineid = 0x408, server_wrong_machineid = 0x408,
server_is_not_running = 0x409, server_is_not_running = 0x409,
server_is_booting = 0x40a, server_is_booting = 0x40a,
server_status_invalid = 0x40b, server_status_invalid = 0x40b,
server_modal_quit = 0x40c, server_modal_quit = 0x40c,
server_version_outdated = 0x40d, server_version_outdated = 0x40d,
server_already_joined = 0x40d, server_already_joined = 0x40d,
server_is_not_shutting_down = 0x40e, server_is_not_shutting_down = 0x40e,
server_max_vs_reached = 0x40f, server_max_vs_reached = 0x40f,
server_unbound = 0x410, server_unbound = 0x410,
server_join_rate_limit_reached = 0x411, server_join_rate_limit_reached = 0x411,
sql = 0x500, sql = 0x500,
database_empty_result = 0x501, database_empty_result = 0x501,
database_duplicate_entry = 0x502, database_duplicate_entry = 0x502,
database_no_modifications = 0x503, database_no_modifications = 0x503,
database_constraint = 0x504, database_constraint = 0x504,
database_reinvoke = 0x505, database_reinvoke = 0x505,
parameter_quote = 0x600, parameter_quote = 0x600,
parameter_invalid_count = 0x601, parameter_invalid_count = 0x601,
parameter_invalid = 0x602, parameter_invalid = 0x602,
parameter_not_found = 0x603, parameter_not_found = 0x603,
parameter_convert = 0x604, parameter_convert = 0x604,
parameter_invalid_size = 0x605, parameter_invalid_size = 0x605,
parameter_missing = 0x606, parameter_missing = 0x606,
parameter_checksum = 0x607, parameter_checksum = 0x607,
vs_critical = 0x700, vs_critical = 0x700,
connection_lost = 0x701, connection_lost = 0x701,
not_connected = 0x702, not_connected = 0x702,
no_cached_connection_info = 0x703, no_cached_connection_info = 0x703,
currently_not_possible = 0x704, currently_not_possible = 0x704,
failed_connection_initialisation = 0x705, failed_connection_initialisation = 0x705,
could_not_resolve_hostname = 0x706, could_not_resolve_hostname = 0x706,
invalid_server_connection_handler_id = 0x707, invalid_server_connection_handler_id = 0x707,
could_not_initialise_input_client = 0x708, could_not_initialise_input_client = 0x708,
clientlibrary_not_initialised = 0x709, clientlibrary_not_initialised = 0x709,
serverlibrary_not_initialised = 0x70a, serverlibrary_not_initialised = 0x70a,
whisper_too_many_targets = 0x70b, whisper_too_many_targets = 0x70b,
whisper_no_targets = 0x70c, whisper_no_targets = 0x70c,
file_invalid_name = 0x800, file_invalid_name = 0x800,
file_invalid_permissions = 0x801, file_invalid_permissions = 0x801,
file_already_exists = 0x802, file_already_exists = 0x802,
file_not_found = 0x803, file_not_found = 0x803,
file_io_error = 0x804, file_io_error = 0x804,
file_invalid_transfer_id = 0x805, file_invalid_transfer_id = 0x805,
file_invalid_path = 0x806, file_invalid_path = 0x806,
file_no_files_available = 0x807, file_no_files_available = 0x807,
file_overwrite_excludes_resume = 0x808, file_overwrite_excludes_resume = 0x808,
file_invalid_size = 0x809, file_invalid_size = 0x809,
file_already_in_use = 0x80a, file_already_in_use = 0x80a,
file_could_not_open_connection = 0x80b, file_could_not_open_connection = 0x80b,
file_no_space_left_on_device = 0x80c, file_no_space_left_on_device = 0x80c,
file_exceeds_file_system_maximum_size = 0x80d, file_exceeds_file_system_maximum_size = 0x80d,
file_transfer_connection_timeout = 0x80e, file_transfer_connection_timeout = 0x80e,
file_connection_lost = 0x80f, file_connection_lost = 0x80f,
file_exceeds_supplied_size = 0x810, file_exceeds_supplied_size = 0x810,
file_transfer_complete = 0x811, file_transfer_complete = 0x811,
file_transfer_canceled = 0x812, file_transfer_canceled = 0x812,
file_transfer_interrupted = 0x813, file_transfer_interrupted = 0x813,
file_transfer_server_quota_exceeded = 0x814, file_transfer_server_quota_exceeded = 0x814,
file_transfer_client_quota_exceeded = 0x815, file_transfer_client_quota_exceeded = 0x815,
file_transfer_reset = 0x816, file_transfer_reset = 0x816,
file_transfer_limit_reached = 0x817, file_transfer_limit_reached = 0x817,
server_insufficeient_permissions = 0xa08, server_insufficeient_permissions = 0xa08,
accounting_slot_limit_reached = 0xb01, accounting_slot_limit_reached = 0xb01,
server_connect_banned = 0xd01, server_connect_banned = 0xd01,
ban_flooding = 0xd03, ban_flooding = 0xd03,
token_invalid_id = 0xf00, token_invalid_id = 0xf00,
web_handshake_invalid = 0x1001, web_handshake_invalid = 0x1001,
web_handshake_unsupported = 0x1001, web_handshake_unsupported = 0x1001,
web_handshake_identity_unsupported = 0x1002, web_handshake_identity_unsupported = 0x1002,
web_handshake_identity_proof_failed = 0x1003, web_handshake_identity_proof_failed = 0x1003,
web_handshake_identity_outdated = 0x1004, web_handshake_identity_outdated = 0x1004,
music_invalid_id = 0x1100, music_invalid_id = 0x1100,
music_limit_reached = 0x1101, music_limit_reached = 0x1101,
music_client_limit_reached = 0x1102, music_client_limit_reached = 0x1102,
music_invalid_player_state = 0x1103, music_invalid_player_state = 0x1103,
music_invalid_action = 0x1104, music_invalid_action = 0x1104,
music_no_player = 0x1105, music_no_player = 0x1105,
music_disabled = 0x1105, music_disabled = 0x1105,
playlist_invalid_id = 0x2100, playlist_invalid_id = 0x2100,
playlist_invalid_song_id = 0x2101, playlist_invalid_song_id = 0x2101,
playlist_already_in_use = 0x2102, playlist_already_in_use = 0x2102,
playlist_is_in_use = 0x2103, playlist_is_in_use = 0x2103,
query_not_exists = 0x1200, query_not_exists = 0x1200,
query_already_exists = 0x1201, query_already_exists = 0x1201,
group_invalid_id = 0x1300, group_invalid_id = 0x1300,
group_name_inuse = 0x1301, group_name_inuse = 0x1301,
group_not_assigned_over_this_server = 0x1302, group_not_assigned_over_this_server = 0x1302,
conversation_invalid_id = 0x2200, conversation_invalid_id = 0x2200,
conversation_more_data = 0x2201, conversation_more_data = 0x2201,
conversation_is_private = 0x2202, conversation_is_private = 0x2202,
custom_error = 0xffff custom_error = 0xffff
}; };
}; };
struct detailed_command_result { struct detailed_command_result {
error::type error_id; error::type error_id;
std::map<std::string, std::string> extra_properties; std::map<std::string, std::string> extra_properties;
}; };
/* /*
* return command_result{permission::b_virtualserver_select_godmode}; => movabs rax,0xa08001700000001; ret; (Only if there is no destructor!) * return command_result{permission::b_virtualserver_select_godmode}; => movabs rax,0xa08001700000001; ret; (Only if there is no destructor!)
* return command_result{permission::b_virtualserver_select_godmode}; => movabs rax,0xa08001700000001; ret; (Only if there is no destructor!) * return command_result{permission::b_virtualserver_select_godmode}; => movabs rax,0xa08001700000001; ret; (Only if there is no destructor!)
* return command_result{error::vs_critical, "unknown error"}; => To a lot of code * return command_result{error::vs_critical, "unknown error"}; => To a lot of code
*/ */
struct command_result { /* fixed size of 8 (64 bits) */ struct command_result { /* fixed size of 8 (64 bits) */
static constexpr uint64_t MASK_ERROR = ~((uint64_t) 1 << (sizeof(error::type) * 8)); static constexpr uint64_t MASK_ERROR = ~((uint64_t) 1 << (sizeof(error::type) * 8));
static constexpr uint64_t MASK_PERMISSION = ~((uint64_t) 1 << (sizeof(permission::PermissionType) * 8)); static constexpr uint64_t MASK_PERMISSION = ~((uint64_t) 1 << (sizeof(permission::PermissionType) * 8));
static constexpr uint8_t OFFSET_ERROR = (8 - sizeof(error::type)) * 8; static constexpr uint8_t OFFSET_ERROR = (8 - sizeof(error::type)) * 8;
static constexpr uint8_t OFFSET_PERMISSION = (8 - sizeof(permission::PermissionType) - sizeof(error::type)) * 8; static constexpr uint8_t OFFSET_PERMISSION = (8 - sizeof(permission::PermissionType) - sizeof(error::type)) * 8;
/* /*
* First bit is a flag bit which switches between detailed and code mode. * First bit is a flag bit which switches between detailed and code mode.
* 0 means detailed (Because then we could interpret data as a ptr (all ptr are 8 bit aligned => 3 zero bits)) * 0 means detailed (Because then we could interpret data as a ptr (all ptr are 8 bit aligned => 3 zero bits))
* bits [0;64] => data ptr (needs to be zero at destruction to avoid memory leaks) * bits [0;64] => data ptr (needs to be zero at destruction to avoid memory leaks)
* *
* 1 means code * 1 means code
* bits [64 - sizeof(error::type);64] => error type | Usually evaluates to [48;64] * bits [64 - sizeof(error::type);64] => error type | Usually evaluates to [48;64]
* bits [64 - sizeof(error::type) - sizeof(permission::PermissionType);64 - sizeof(error::type)] => permission id | Usually evaluates to [32;48] * bits [64 - sizeof(error::type) - sizeof(permission::PermissionType);64 - sizeof(error::type)] => permission id | Usually evaluates to [32;48]
*/ */
uint64_t data = 0; uint64_t data = 0;
/* Test for mode 1 as described before */ /* Test for mode 1 as described before */
static_assert(sizeof(permission::PermissionType) * 8 + sizeof(error::type) * 8 <= 62); static_assert(sizeof(permission::PermissionType) * 8 + sizeof(error::type) * 8 <= 62);
[[nodiscard]] inline error::type error_code() const { [[nodiscard]] inline error::type error_code() const {
if(this->is_detailed()) return this->details()->error_id; if(this->is_detailed()) return this->details()->error_id;
return (error::type) ((this->data >> OFFSET_ERROR) & MASK_ERROR); return (error::type) ((this->data >> OFFSET_ERROR) & MASK_ERROR);
} }
[[nodiscard]] inline bool is_permission_error() const { [[nodiscard]] inline bool is_permission_error() const {
return this->error_code() == error::server_insufficeient_permissions; return this->error_code() == error::server_insufficeient_permissions;
} }
[[nodiscard]] inline permission::PermissionType permission_id() const { [[nodiscard]] inline permission::PermissionType permission_id() const {
if(this->is_detailed()) return (permission::PermissionType) -1; /* not supported */ if(this->is_detailed()) return (permission::PermissionType) -1; /* not supported */
return (permission::PermissionType) ((this->data >> OFFSET_PERMISSION) & MASK_PERMISSION); return (permission::PermissionType) ((this->data >> OFFSET_PERMISSION) & MASK_PERMISSION);
} }
[[nodiscard]] inline const detailed_command_result* details() const { return (detailed_command_result*) this->data; } [[nodiscard]] inline const detailed_command_result* details() const { return (detailed_command_result*) this->data; }
[[nodiscard]] inline detailed_command_result* details() { return (detailed_command_result*) this->data; } [[nodiscard]] inline detailed_command_result* details() { return (detailed_command_result*) this->data; }
[[nodiscard]] inline bool is_detailed() const { [[nodiscard]] inline bool is_detailed() const {
return (this->data & 0x1UL) == 0; return (this->data & 0x1UL) == 0;
} }
inline std::unique_ptr<detailed_command_result> release_details() { inline std::unique_ptr<detailed_command_result> release_details() {
if(!this->is_detailed()) return nullptr; if(!this->is_detailed()) return nullptr;
auto result = this->details(); auto result = this->details();
this->data = 0; this->data = 0;
return std::unique_ptr<detailed_command_result>{result}; return std::unique_ptr<detailed_command_result>{result};
} }
/* Attention: Releases the internal detailed pointer! */ /* Attention: Releases the internal detailed pointer! */
inline CommandResult as_command_result(); inline CommandResult as_command_result();
#ifndef _NDEBUG /* We dont need to secure that because gcc deduct us to an uint64_t and the only advantage is the mem leak test which is deactivated anyways */ #ifndef _NDEBUG /* We dont need to secure that because gcc deduct us to an uint64_t and the only advantage is the mem leak test which is deactivated anyways */
command_result(command_result&) = delete; command_result(command_result&) = delete;
command_result(const command_result&) = delete; command_result(const command_result&) = delete;
command_result(command_result&& other) : data(other.data) { command_result(command_result&& other) : data(other.data) {
other.data = 0; other.data = 0;
} }
#endif #endif
command_result() = default; command_result() = default;
explicit command_result(permission::PermissionType permission) { explicit command_result(permission::PermissionType permission) {
this->data = 0x01; /* the the type to 1 */ this->data = 0x01; /* the the type to 1 */
this->data |= (uint64_t) error::server_insufficeient_permissions << OFFSET_ERROR; this->data |= (uint64_t) error::server_insufficeient_permissions << OFFSET_ERROR;
this->data |= (uint64_t) permission << OFFSET_PERMISSION; this->data |= (uint64_t) permission << OFFSET_PERMISSION;
} }
explicit command_result(error::type error) { explicit command_result(error::type error) {
this->data = 0x01; /* the the type to 1 */ this->data = 0x01; /* the the type to 1 */
this->data |= (uint64_t) error << (8 - sizeof(error::type)) * 8; this->data |= (uint64_t) error << (8 - sizeof(error::type)) * 8;
} }
command_result(error::type error, const std::string& message) { command_result(error::type error, const std::string& message) {
auto details_ptr = new detailed_command_result{}; auto details_ptr = new detailed_command_result{};
assert(((uintptr_t) details_ptr & 0x03U) == 0); // must be aligned! assert(((uintptr_t) details_ptr & 0x03U) == 0); // must be aligned!
this->data = (uintptr_t) details_ptr; this->data = (uintptr_t) details_ptr;
details_ptr->error_id = error; details_ptr->error_id = error;
details_ptr->extra_properties["extra_msg"] = message; details_ptr->extra_properties["extra_msg"] = message;
} }
command_result(error::type error, const std::map<std::string, std::string>& properties) : command_result{error, std::string{""}} { command_result(error::type error, const std::map<std::string, std::string>& properties) : command_result{error, std::string{""}} {
assert(this->is_detailed()); assert(this->is_detailed());
this->details()->extra_properties = properties; this->details()->extra_properties = properties;
} }
#ifndef _NDEBUG #ifndef _NDEBUG
/* if we're not using any debug we dont have to use a deconstructor. A deconstructor prevent a direct uint64_t return as described above */ /* if we're not using any debug we dont have to use a deconstructor. A deconstructor prevent a direct uint64_t return as described above */
~command_result() { ~command_result() {
if((this->data & 0x01) == 0x00) { if((this->data & 0x01) == 0x00) {
// this->details needs to be removed 'till this gets destructed // this->details needs to be removed 'till this gets destructed
assert(this->data == 0); assert(this->data == 0);
} }
} }
#endif #endif
}; };
static_assert(sizeof(command_result) == 8); static_assert(sizeof(command_result) == 8);
struct ErrorType { struct ErrorType {
public: public:
static ErrorType Success; static ErrorType Success;
static ErrorType Costume; static ErrorType Costume;
static ErrorType VSError; static ErrorType VSError;
static ErrorType DBEmpty; static ErrorType DBEmpty;
ErrorType(const uint16_t errorId, std::string name, std::string message) : errorId(errorId), name(std::move(name)), message(std::move(message)) {} ErrorType(const uint16_t errorId, std::string name, std::string message) : errorId(errorId), name(std::move(name)), message(std::move(message)) {}
ErrorType(const ErrorType& ref) = default; ErrorType(const ErrorType& ref) = default;
ErrorType(ErrorType&& ref) : errorId(ref.errorId), name(std::move(ref.name)), message(std::move(ref.message)) {} ErrorType(ErrorType&& ref) : errorId(ref.errorId), name(std::move(ref.name)), message(std::move(ref.message)) {}
uint16_t errorId; uint16_t errorId;
std::string name; std::string name;
std::string message; std::string message;
bool operator==(const ErrorType& ref) const { bool operator==(const ErrorType& ref) const {
return errorId == ref.errorId; return errorId == ref.errorId;
} }
bool operator!=(const ErrorType& ref) const { return !operator==(ref); } bool operator!=(const ErrorType& ref) const { return !operator==(ref); }
ErrorType& operator=(const ErrorType& ref) { ErrorType& operator=(const ErrorType& ref) {
errorId = ref.errorId; errorId = ref.errorId;
name = ref.name; name = ref.name;
message = ref.message; message = ref.message;
return *this; return *this;
} }
/** /**
* @return true if fail * @return true if fail
*/ */
bool operator!() const { bool operator!() const {
return errorId != 0; return errorId != 0;
} }
}; };
extern const std::vector<ErrorType> avariableErrors; extern const std::vector<ErrorType> avariableErrors;
extern ErrorType findError(uint16_t errorId); extern ErrorType findError(uint16_t errorId);
extern ErrorType findError(std::string key); extern ErrorType findError(std::string key);
enum CommandResultType { enum CommandResultType {
GENERAL, GENERAL,
PERM_ERROR PERM_ERROR
}; };
struct CommandResult { struct CommandResult {
public: public:
static CommandResult Success; static CommandResult Success;
static CommandResult NotImplemented; static CommandResult NotImplemented;
CommandResult(const CommandResult& ref) : _type(ref._type), error(ref.error), extraProperties(ref.extraProperties) {} CommandResult(const CommandResult& ref) : _type(ref._type), error(ref.error), extraProperties(ref.extraProperties) {}
CommandResult(CommandResult&& ref) : _type(ref._type), error(ref.error), extraProperties(ref.extraProperties) {} CommandResult(CommandResult&& ref) : _type(ref._type), error(ref.error), extraProperties(ref.extraProperties) {}
CommandResult(ErrorType error, const std::string &extraMsg = "") : error(std::move(error)) { if(extraMsg.empty()) return; /*extraProperties["extramsg"] = extraMsg; */extraProperties["extra_msg"] = extraMsg; } CommandResult(ErrorType error, const std::string &extraMsg = "") : error(std::move(error)) { if(extraMsg.empty()) return; /*extraProperties["extramsg"] = extraMsg; */extraProperties["extra_msg"] = extraMsg; }
CommandResult(std::string error, const std::string &extraMsg = "") : error(findError(std::move(error))) { if(extraMsg.empty()) return; /*extraProperties["extramsg"] = extraMsg; */extraProperties["extra_msg"] = extraMsg; } CommandResult(std::string error, const std::string &extraMsg = "") : error(findError(std::move(error))) { if(extraMsg.empty()) return; /*extraProperties["extramsg"] = extraMsg; */extraProperties["extra_msg"] = extraMsg; }
CommandResult() : CommandResult(ErrorType::Success, ""){} CommandResult() : CommandResult(ErrorType::Success, ""){}
CommandResult(ErrorType error, std::map<std::string, std::string> details) : error(error), extraProperties(std::move(details)) {} CommandResult(ErrorType error, std::map<std::string, std::string> details) : error(error), extraProperties(std::move(details)) {}
bool operator==(const CommandResult& ref){ bool operator==(const CommandResult& ref){
return this->error == ref.error && ref.extraProperties == this->extraProperties; return this->error == ref.error && ref.extraProperties == this->extraProperties;
} }
CommandResult& operator=(const CommandResult& ref)= default; CommandResult& operator=(const CommandResult& ref)= default;
/** /**
* @return true if fail * @return true if fail
*/ */
bool operator!() const { bool operator!() const {
return this->error != ErrorType::Success; return this->error != ErrorType::Success;
} }
virtual CommandResultType type(){ return _type; } virtual CommandResultType type(){ return _type; }
ErrorType error; ErrorType error;
std::map<std::string, std::string> extraProperties; std::map<std::string, std::string> extraProperties;
CommandResultType _type = CommandResultType::GENERAL; CommandResultType _type = CommandResultType::GENERAL;
}; };
struct CommandResultPermissionError : public CommandResult { struct CommandResultPermissionError : public CommandResult {
public: public:
CommandResultPermissionError(permission::PermissionType error, const std::string &extraMsg = ""); CommandResultPermissionError(permission::PermissionType error, const std::string &extraMsg = "");
}; };
CommandResult command_result::as_command_result() { CommandResult command_result::as_command_result() {
if(this->is_detailed()) { if(this->is_detailed()) {
const auto details = this->details(); const auto details = this->details();
auto result = CommandResult{findError(details->error_id), details->extra_properties}; auto result = CommandResult{findError(details->error_id), details->extra_properties};
this->release_details(); this->release_details();
return result; return result;
} else { } else {
const auto code = this->error_code(); const auto code = this->error_code();
auto error = findError(this->error_code()); auto error = findError(this->error_code());
if(code == error::server_insufficeient_permissions) if(code == error::server_insufficeient_permissions)
return CommandResultPermissionError{(permission::PermissionType) this->permission_id()}; return CommandResultPermissionError{(permission::PermissionType) this->permission_id()};
else else
return CommandResult{error}; return CommandResult{error};
} }
} }
} }
#undef _NDEBUG #undef _NDEBUG

View File

@ -1,90 +1,90 @@
#pragma once #pragma once
#include <mutex> #include <mutex>
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <string> #include <string>
#include <thread> #include <thread>
#include <condition_variable> #include <condition_variable>
namespace ts { namespace ts {
namespace event { namespace event {
class EventExecutor; class EventExecutor;
class EventEntry { class EventEntry {
friend class EventExecutor; friend class EventExecutor;
public: public:
virtual void event_execute(const std::chrono::system_clock::time_point& /* scheduled timestamp */) = 0; virtual void event_execute(const std::chrono::system_clock::time_point& /* scheduled timestamp */) = 0;
private: private:
void* _event_ptr = nullptr; void* _event_ptr = nullptr;
}; };
template <typename class_t> template <typename class_t>
class ProxiedEventEntry : public event::EventEntry { class ProxiedEventEntry : public event::EventEntry {
public: public:
using callback_t = void(class_t::*)(const std::chrono::system_clock::time_point &); using callback_t = void(class_t::*)(const std::chrono::system_clock::time_point &);
using static_callback_t = void(*)(class_t *, const std::chrono::system_clock::time_point &); using static_callback_t = void(*)(class_t *, const std::chrono::system_clock::time_point &);
ProxiedEventEntry(const std::shared_ptr<class_t>& _instance, callback_t callback) : instance(_instance), callback(callback) { } ProxiedEventEntry(const std::shared_ptr<class_t>& _instance, callback_t callback) : instance(_instance), callback(callback) { }
std::weak_ptr<class_t> instance; std::weak_ptr<class_t> instance;
callback_t callback; callback_t callback;
void event_execute(const std::chrono::system_clock::time_point &point) override { void event_execute(const std::chrono::system_clock::time_point &point) override {
auto _instance = this->instance.lock(); auto _instance = this->instance.lock();
if(!_instance) if(!_instance)
return; return;
auto callback_ptr = (void**) &this->callback; auto callback_ptr = (void**) &this->callback;
(*(static_callback_t*) callback_ptr)(&*_instance, point); (*(static_callback_t*) callback_ptr)(&*_instance, point);
} }
}; };
class EventExecutor { class EventExecutor {
public: public:
explicit EventExecutor(const std::string& /* thread prefix */); explicit EventExecutor(const std::string& /* thread prefix */);
virtual ~EventExecutor(); virtual ~EventExecutor();
bool initialize(int /* num threads */); bool initialize(int /* num threads */);
bool schedule(const std::shared_ptr<EventEntry>& /* entry */); bool schedule(const std::shared_ptr<EventEntry>& /* entry */);
bool cancel(const std::shared_ptr<EventEntry>& /* entry */); /* Note: Will not cancel already running executes */ bool cancel(const std::shared_ptr<EventEntry>& /* entry */); /* Note: Will not cancel already running executes */
void shutdown(); void shutdown();
inline const std::string& thread_prefix() const { return this->_thread_prefix; } inline const std::string& thread_prefix() const { return this->_thread_prefix; }
void threads(int /* num threads */); void threads(int /* num threads */);
inline int threads() const { return this->target_threads; } inline int threads() const { return this->target_threads; }
private: private:
struct LinkedEntry { struct LinkedEntry {
LinkedEntry* previous; LinkedEntry* previous;
LinkedEntry* next; LinkedEntry* next;
std::chrono::system_clock::time_point scheduled; std::chrono::system_clock::time_point scheduled;
std::weak_ptr<EventEntry> entry; std::weak_ptr<EventEntry> entry;
}; };
static void _executor(EventExecutor*); static void _executor(EventExecutor*);
void _spawn_executor(std::unique_lock<std::mutex>&); void _spawn_executor(std::unique_lock<std::mutex>&);
void _shutdown(std::unique_lock<std::mutex>&); void _shutdown(std::unique_lock<std::mutex>&);
void _reset_events(std::unique_lock<std::mutex>&); void _reset_events(std::unique_lock<std::mutex>&);
#ifndef WIN32 #ifndef WIN32
void _reassign_thread_names(std::unique_lock<std::mutex>&); void _reassign_thread_names(std::unique_lock<std::mutex>&);
#endif #endif
bool should_shutdown = true; bool should_shutdown = true;
bool should_adjust = false; /* thread adjustments */ bool should_adjust = false; /* thread adjustments */
int target_threads = 0; int target_threads = 0;
std::vector<std::thread> _threads; std::vector<std::thread> _threads;
std::mutex lock; std::mutex lock;
std::condition_variable condition; std::condition_variable condition;
LinkedEntry* head = nullptr; LinkedEntry* head = nullptr;
LinkedEntry* tail = nullptr; LinkedEntry* tail = nullptr;
std::string _thread_prefix; std::string _thread_prefix;
}; };
} }
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,242 +1,242 @@
// //
// Created by wolverindev on 07.10.17. // Created by wolverindev on 07.10.17.
// //
#include <cstring> #include <cstring>
#include <iostream> #include <iostream>
#include <bitset> #include <bitset>
#include "Packet.h" #include "Packet.h"
#include "buffers.h" #include "buffers.h"
#include "misc/endianness.h" #include "misc/endianness.h"
using namespace std; using namespace std;
namespace ts { namespace ts {
namespace protocol { namespace protocol {
PacketTypeInfo::PacketTypeInfo(const std::string& name, PacketType type, bool ack, int max_length) noexcept { PacketTypeInfo::PacketTypeInfo(const std::string& name, PacketType type, bool ack, int max_length) noexcept {
this->data = new PacketTypeProperties{name, type, max_length, ack}; this->data = new PacketTypeProperties{name, type, max_length, ack};
this->owns_data = true; this->owns_data = true;
if(type < 0x0F) if(type < 0x0F)
types.insert({type, *this}); types.insert({type, *this});
} }
PacketTypeInfo::~PacketTypeInfo() { PacketTypeInfo::~PacketTypeInfo() {
if(this->owns_data) if(this->owns_data)
delete this->data; delete this->data;
} }
PacketTypeInfo::PacketTypeInfo(const PacketTypeInfo &red) : data(red.data) { } PacketTypeInfo::PacketTypeInfo(const PacketTypeInfo &red) : data(red.data) { }
std::map<int, PacketTypeInfo> PacketTypeInfo::types; std::map<int, PacketTypeInfo> PacketTypeInfo::types;
PacketTypeInfo PacketTypeInfo::fromid(int id) { PacketTypeInfo PacketTypeInfo::fromid(int id) {
for(const auto& elm : types) for(const auto& elm : types)
if(elm.first == id) return elm.second; if(elm.first == id) return elm.second;
return PacketTypeInfo::Undefined; return PacketTypeInfo::Undefined;
} }
PacketTypeInfo PacketTypeInfo::Voice = {"Voice", PacketType::VOICE, false, 1024}; PacketTypeInfo PacketTypeInfo::Voice = {"Voice", PacketType::VOICE, false, 1024};
PacketTypeInfo PacketTypeInfo::VoiceWhisper = {"VoiceWhisper", PacketType::VOICE_WHISPER, false, 1024}; PacketTypeInfo PacketTypeInfo::VoiceWhisper = {"VoiceWhisper", PacketType::VOICE_WHISPER, false, 1024};
PacketTypeInfo PacketTypeInfo::Command = {"Command", PacketType::COMMAND, true, 487}; PacketTypeInfo PacketTypeInfo::Command = {"Command", PacketType::COMMAND, true, 487};
PacketTypeInfo PacketTypeInfo::CommandLow = {"CommandLow", PacketType::COMMAND_LOW, true, 487}; PacketTypeInfo PacketTypeInfo::CommandLow = {"CommandLow", PacketType::COMMAND_LOW, true, 487};
PacketTypeInfo PacketTypeInfo::Ping = {"Ping", PacketType::PING, false, 1024}; PacketTypeInfo PacketTypeInfo::Ping = {"Ping", PacketType::PING, false, 1024};
PacketTypeInfo PacketTypeInfo::Pong = {"Pong", PacketType::PONG, false, 1024}; PacketTypeInfo PacketTypeInfo::Pong = {"Pong", PacketType::PONG, false, 1024};
PacketTypeInfo PacketTypeInfo::Ack = {"Ack", PacketType::ACK, false, 1024}; PacketTypeInfo PacketTypeInfo::Ack = {"Ack", PacketType::ACK, false, 1024};
PacketTypeInfo PacketTypeInfo::AckLow = {"AckLow", PacketType::ACK_LOW, false, 1024}; PacketTypeInfo PacketTypeInfo::AckLow = {"AckLow", PacketType::ACK_LOW, false, 1024};
PacketTypeInfo PacketTypeInfo::Init1 = {"Init1", PacketType::INIT1, false, 1024}; PacketTypeInfo PacketTypeInfo::Init1 = {"Init1", PacketType::INIT1, false, 1024};
PacketTypeInfo PacketTypeInfo::Undefined = {"Undefined", PacketType::UNDEFINED, false, 1024}; PacketTypeInfo PacketTypeInfo::Undefined = {"Undefined", PacketType::UNDEFINED, false, 1024};
namespace PacketFlag { namespace PacketFlag {
std::string to_string(PacketFlag flag){ std::string to_string(PacketFlag flag){
switch(flag){ switch(flag){
case Fragmented: case Fragmented:
return "Fragmented"; return "Fragmented";
case NewProtocol: case NewProtocol:
return "NewProtocol"; return "NewProtocol";
case Compressed: case Compressed:
return "Compressed"; return "Compressed";
case Unencrypted: case Unencrypted:
return "Unencrypted"; return "Unencrypted";
default: default:
return "None"; return "None";
} }
} }
} }
BasicPacket::BasicPacket(size_t header_length, size_t data_length) { BasicPacket::BasicPacket(size_t header_length, size_t data_length) {
this->_header_length = (uint8_t) header_length; this->_header_length = (uint8_t) header_length;
this->_buffer = pipes::buffer(MAC_SIZE + this->_header_length + data_length); this->_buffer = pipes::buffer(MAC_SIZE + this->_header_length + data_length);
memset(this->_buffer.data_ptr(), 0, this->_buffer.length()); memset(this->_buffer.data_ptr(), 0, this->_buffer.length());
} }
BasicPacket::~BasicPacket() {} BasicPacket::~BasicPacket() {}
void BasicPacket::append_data(const std::vector<pipes::buffer> &data) { void BasicPacket::append_data(const std::vector<pipes::buffer> &data) {
size_t length = 0; size_t length = 0;
for(const auto& buffer : data) for(const auto& buffer : data)
length += buffer.length(); length += buffer.length();
/* we've to allocate a new buffer because out buffer is fixed in size */ /* we've to allocate a new buffer because out buffer is fixed in size */
size_t index = this->_buffer.length(); size_t index = this->_buffer.length();
auto new_buffer = buffer::allocate_buffer(length + index); auto new_buffer = buffer::allocate_buffer(length + index);
new_buffer.write(this->_buffer, index); new_buffer.write(this->_buffer, index);
for(const auto& buffer : data) { for(const auto& buffer : data) {
new_buffer.write(buffer, buffer.length(), index); new_buffer.write(buffer, buffer.length(), index);
index += buffer.length(); index += buffer.length();
} }
this->_buffer = new_buffer; this->_buffer = new_buffer;
} }
std::string BasicPacket::flags() const { std::string BasicPacket::flags() const {
std::string result; std::string result;
if(this->has_flag(PacketFlag::Unencrypted)) result += string(result.empty() ? "" : " | ") + "Unencrypted"; if(this->has_flag(PacketFlag::Unencrypted)) result += string(result.empty() ? "" : " | ") + "Unencrypted";
if(this->has_flag(PacketFlag::Compressed)) result += string(result.empty() ? "" : " | ") + "Compressed"; if(this->has_flag(PacketFlag::Compressed)) result += string(result.empty() ? "" : " | ") + "Compressed";
if(this->has_flag(PacketFlag::Fragmented)) result += string(result.empty() ? "" : " | ") + "Fragmented"; if(this->has_flag(PacketFlag::Fragmented)) result += string(result.empty() ? "" : " | ") + "Fragmented";
if(this->has_flag(PacketFlag::NewProtocol)) result += string(result.empty() ? "" : " | ") + "NewProtocol"; if(this->has_flag(PacketFlag::NewProtocol)) result += string(result.empty() ? "" : " | ") + "NewProtocol";
if(result.empty()) result = "none"; if(result.empty()) result = "none";
return result; return result;
} }
void BasicPacket::applyPacketId(PacketIdManager& manager) { void BasicPacket::applyPacketId(PacketIdManager& manager) {
this->applyPacketId(manager.nextPacketId(this->type()), manager.generationId(this->type())); this->applyPacketId(manager.nextPacketId(this->type()), manager.generationId(this->type()));
} }
void BasicPacket::applyPacketId(uint16_t packetId, uint16_t generationId) { void BasicPacket::applyPacketId(uint16_t packetId, uint16_t generationId) {
if(this->memory_state.id_branded) if(this->memory_state.id_branded)
throw std::logic_error("Packet already got a packet id!"); throw std::logic_error("Packet already got a packet id!");
this->memory_state.id_branded = true; this->memory_state.id_branded = true;
this->setPacketId(packetId, generationId); this->setPacketId(packetId, generationId);
} }
Command BasicPacket::asCommand() { Command BasicPacket::asCommand() {
return Command::parse(this->data()); return Command::parse(this->data());
} }
/** /**
* @param buffer -> [mac][Header [uint16 BE packetId | [uint8](4bit flags | 4bit type)]][Data] * @param buffer -> [mac][Header [uint16 BE packetId | [uint8](4bit flags | 4bit type)]][Data]
* @return * @return
*/ */
std::unique_ptr<ServerPacket> ServerPacket::from_buffer(const pipes::buffer_view &buffer) { std::unique_ptr<ServerPacket> ServerPacket::from_buffer(const pipes::buffer_view &buffer) {
auto result = make_unique<ServerPacket>(); auto result = make_unique<ServerPacket>();
result->_buffer = buffer.own_buffer(); result->_buffer = buffer.own_buffer();
result->_header_length = SERVER_HEADER_SIZE; result->_header_length = SERVER_HEADER_SIZE;
return result; return result;
} }
ServerPacket::ServerPacket(uint8_t flagMask, const pipes::buffer_view& data) : BasicPacket(SERVER_HEADER_SIZE, data.length()) { ServerPacket::ServerPacket(uint8_t flagMask, const pipes::buffer_view& data) : BasicPacket(SERVER_HEADER_SIZE, data.length()) {
this->header()[2] = flagMask; this->header()[2] = flagMask;
memcpy(this->data().data_ptr(), data.data_ptr(), data.length()); memcpy(this->data().data_ptr(), data.data_ptr(), data.length());
} }
ServerPacket::ServerPacket(const PacketTypeInfo& type, const pipes::buffer_view& data) : BasicPacket(SERVER_HEADER_SIZE, data.length()) { ServerPacket::ServerPacket(const PacketTypeInfo& type, const pipes::buffer_view& data) : BasicPacket(SERVER_HEADER_SIZE, data.length()) {
this->header()[2] |= (uint8_t) type.type(); this->header()[2] |= (uint8_t) type.type();
memcpy(this->data().data_ptr(), data.data_ptr(), data.length()); memcpy(this->data().data_ptr(), data.data_ptr(), data.length());
} }
ServerPacket::ServerPacket(ts::protocol::PacketTypeInfo type, size_t data_length) : BasicPacket(SERVER_HEADER_SIZE, data_length) { ServerPacket::ServerPacket(ts::protocol::PacketTypeInfo type, size_t data_length) : BasicPacket(SERVER_HEADER_SIZE, data_length) {
this->header()[2] |= type.type(); this->header()[2] |= type.type();
} }
ServerPacket::~ServerPacket() {} ServerPacket::~ServerPacket() {}
uint16_t ServerPacket::packetId() const { uint16_t ServerPacket::packetId() const {
return be2le16(&this->header()[0]); return be2le16(&this->header()[0]);
} }
void ServerPacket::setPacketId(uint16_t pkId, uint16_t gen) { void ServerPacket::setPacketId(uint16_t pkId, uint16_t gen) {
le2be16(pkId, &this->header()[0]); le2be16(pkId, &this->header()[0]);
this->genId = gen; this->genId = gen;
} }
uint16_t ServerPacket::generationId() const { uint16_t ServerPacket::generationId() const {
return this->genId; return this->genId;
} }
PacketTypeInfo ServerPacket::type() const { PacketTypeInfo ServerPacket::type() const {
return PacketTypeInfo::fromid(this->header()[2] & 0xF); return PacketTypeInfo::fromid(this->header()[2] & 0xF);
} }
std::unique_ptr<ClientPacket> ClientPacket::from_buffer(const pipes::buffer_view &buffer) { std::unique_ptr<ClientPacket> ClientPacket::from_buffer(const pipes::buffer_view &buffer) {
auto result = make_unique<ClientPacket>(); auto result = make_unique<ClientPacket>();
result->_buffer = buffer.own_buffer(); result->_buffer = buffer.own_buffer();
result->_header_length = CLIENT_HEADER_SIZE; result->_header_length = CLIENT_HEADER_SIZE;
return result; return result;
} }
ClientPacket::ClientPacket(const PacketTypeInfo &type, const pipes::buffer_view& data) : BasicPacket(CLIENT_HEADER_SIZE, data.length()) { ClientPacket::ClientPacket(const PacketTypeInfo &type, const pipes::buffer_view& data) : BasicPacket(CLIENT_HEADER_SIZE, data.length()) {
this->header()[4] = type.type() & 0xF; this->header()[4] = type.type() & 0xF;
memcpy(this->data().data_ptr(), data.data_ptr(), data.length()); memcpy(this->data().data_ptr(), data.data_ptr(), data.length());
} }
ClientPacket::ClientPacket(const PacketTypeInfo &type, uint8_t flag_mask, const pipes::buffer_view& data) : ClientPacket(type, data) { ClientPacket::ClientPacket(const PacketTypeInfo &type, uint8_t flag_mask, const pipes::buffer_view& data) : ClientPacket(type, data) {
this->header()[4] |= flag_mask; this->header()[4] |= flag_mask;
} }
ClientPacket::~ClientPacket() {} ClientPacket::~ClientPacket() {}
uint16_t ClientPacket::packetId() const { uint16_t ClientPacket::packetId() const {
return be2le16(&this->header()[0]); return be2le16(&this->header()[0]);
} }
uint16_t ClientPacket::generationId() const { uint16_t ClientPacket::generationId() const {
return this->genId; return this->genId;
} }
PacketTypeInfo ClientPacket::type() const { PacketTypeInfo ClientPacket::type() const {
return PacketTypeInfo::fromid(this->header()[4] & 0xF); return PacketTypeInfo::fromid(this->header()[4] & 0xF);
} }
void ClientPacket::type(const ts::protocol::PacketTypeInfo &type) { void ClientPacket::type(const ts::protocol::PacketTypeInfo &type) {
auto& field = this->header().data_ptr<uint8_t>()[4]; auto& field = this->header().data_ptr<uint8_t>()[4];
field &= (uint8_t) ~0xF; field &= (uint8_t) ~0xF;
field |= type.type(); field |= type.type();
} }
void ClientPacket::setPacketId(uint16_t pkId, uint16_t gen) { void ClientPacket::setPacketId(uint16_t pkId, uint16_t gen) {
this->header()[0] = (uint8_t) ((pkId >> 8) & 0xFF); this->header()[0] = (uint8_t) ((pkId >> 8) & 0xFF);
this->header()[1] = (uint8_t) ((pkId >> 0) & 0xFF); this->header()[1] = (uint8_t) ((pkId >> 0) & 0xFF);
this->genId = gen; this->genId = gen;
} }
uint16_t ClientPacket::clientId() const { uint16_t ClientPacket::clientId() const {
return be2le16(&this->header()[2]); return be2le16(&this->header()[2]);
} }
void ClientPacket::clientId(uint16_t clId) { void ClientPacket::clientId(uint16_t clId) {
this->header()[2] = clId >> 8; this->header()[2] = clId >> 8;
this->header()[3] = clId & 0xFF; this->header()[3] = clId & 0xFF;
} }
uint16_t ClientPacketParser::packet_id() const { return be2le16(this->_buffer.data_ptr<uint8_t>(), ClientPacketParser::kHeaderOffset + 0); } uint16_t ClientPacketParser::packet_id() const { return be2le16(this->_buffer.data_ptr<uint8_t>(), ClientPacketParser::kHeaderOffset + 0); }
uint16_t ClientPacketParser::client_id() const { return be2le16(this->_buffer.data_ptr<uint8_t>(), ClientPacketParser::kHeaderOffset + 2); } uint16_t ClientPacketParser::client_id() const { return be2le16(this->_buffer.data_ptr<uint8_t>(), ClientPacketParser::kHeaderOffset + 2); }
uint8_t ClientPacketParser::type() const { return (uint8_t) this->_buffer[ClientPacketParser::kHeaderOffset + 4] & 0xFU; } uint8_t ClientPacketParser::type() const { return (uint8_t) this->_buffer[ClientPacketParser::kHeaderOffset + 4] & 0xFU; }
uint8_t ClientPacketParser::flags() const { return (uint8_t) this->_buffer[ClientPacketParser::kHeaderOffset + 4] & 0xF0U; } uint8_t ClientPacketParser::flags() const { return (uint8_t) this->_buffer[ClientPacketParser::kHeaderOffset + 4] & 0xF0U; }
bool ClientPacketParser::is_encrypted() const { bool ClientPacketParser::is_encrypted() const {
if(this->decrypted) return false; if(this->decrypted) return false;
return (this->flags() & PacketFlag::Unencrypted) == 0; return (this->flags() & PacketFlag::Unencrypted) == 0;
} }
bool ClientPacketParser::is_compressed() const { bool ClientPacketParser::is_compressed() const {
if(this->uncompressed) return false; if(this->uncompressed) return false;
return (this->flags() & PacketFlag::Compressed) > 0; return (this->flags() & PacketFlag::Compressed) > 0;
} }
bool ClientPacketParser::is_fragmented() const { bool ClientPacketParser::is_fragmented() const {
if(this->defragmented) return false; if(this->defragmented) return false;
return (this->flags() & PacketFlag::Fragmented) > 0; return (this->flags() & PacketFlag::Fragmented) > 0;
} }
} }
} }

View File

@ -1,371 +1,371 @@
#pragma once #pragma once
#include <cstring> #include <cstring>
#include <string> #include <string>
#include <map> #include <map>
#include <utility> #include <utility>
#include <ThreadPool/Future.h> #include <ThreadPool/Future.h>
#include <pipes/buffer.h> #include <pipes/buffer.h>
#include "../query/Command.h" #include "../query/Command.h"
namespace ts { namespace ts {
namespace protocol { namespace protocol {
enum PacketType : uint8_t { enum PacketType : uint8_t {
VOICE = 0x00, VOICE = 0x00,
VOICE_WHISPER = 0x01, VOICE_WHISPER = 0x01,
COMMAND = 0x02, COMMAND = 0x02,
COMMAND_LOW = 0x03, COMMAND_LOW = 0x03,
PING = 0x04, PING = 0x04,
PONG = 0x05, PONG = 0x05,
ACK = 0x06, ACK = 0x06,
ACK_LOW = 0x07, ACK_LOW = 0x07,
INIT1 = 0x08, INIT1 = 0x08,
PACKET_MAX = INIT1, PACKET_MAX = INIT1,
UNDEFINED = 0xFF UNDEFINED = 0xFF
}; };
struct PacketTypeProperties { struct PacketTypeProperties {
std::string name; std::string name;
PacketType type; PacketType type;
int max_length; int max_length;
bool requireAcknowledge; bool requireAcknowledge;
}; };
class PacketTypeInfo { class PacketTypeInfo {
public: public:
static PacketTypeInfo Voice; static PacketTypeInfo Voice;
static PacketTypeInfo VoiceWhisper; static PacketTypeInfo VoiceWhisper;
static PacketTypeInfo Command; static PacketTypeInfo Command;
static PacketTypeInfo CommandLow; static PacketTypeInfo CommandLow;
static PacketTypeInfo Ping; static PacketTypeInfo Ping;
static PacketTypeInfo Pong; static PacketTypeInfo Pong;
static PacketTypeInfo Ack; static PacketTypeInfo Ack;
static PacketTypeInfo AckLow; static PacketTypeInfo AckLow;
static PacketTypeInfo Init1; static PacketTypeInfo Init1;
static PacketTypeInfo Undefined; static PacketTypeInfo Undefined;
static PacketTypeInfo fromid(int id); static PacketTypeInfo fromid(int id);
std::string name() const { return data->name; } std::string name() const { return data->name; }
PacketType type() const { return data->type; } PacketType type() const { return data->type; }
bool requireAcknowledge(){ return data->requireAcknowledge; } bool requireAcknowledge(){ return data->requireAcknowledge; }
bool operator==(const PacketTypeInfo& other) const { bool operator==(const PacketTypeInfo& other) const {
return other.data->type == this->data->type; return other.data->type == this->data->type;
} }
bool operator!=(const PacketTypeInfo& other){ bool operator!=(const PacketTypeInfo& other){
return other.data->type != this->data->type; return other.data->type != this->data->type;
} }
int max_length() const { return data->max_length; } int max_length() const { return data->max_length; }
inline bool fragmentable() { return *this == PacketTypeInfo::Command || *this == PacketTypeInfo::CommandLow; } inline bool fragmentable() { return *this == PacketTypeInfo::Command || *this == PacketTypeInfo::CommandLow; }
inline bool compressable() { return *this == PacketTypeInfo::Command || *this == PacketTypeInfo::CommandLow; } inline bool compressable() { return *this == PacketTypeInfo::Command || *this == PacketTypeInfo::CommandLow; }
PacketTypeInfo(const PacketTypeInfo&); PacketTypeInfo(const PacketTypeInfo&);
PacketTypeInfo(PacketTypeInfo&& remote) : data(remote.data) {} PacketTypeInfo(PacketTypeInfo&& remote) : data(remote.data) {}
~PacketTypeInfo(); ~PacketTypeInfo();
private: private:
static std::map<int, PacketTypeInfo> types; static std::map<int, PacketTypeInfo> types;
PacketTypeInfo(const std::string&, PacketType, bool, int) noexcept; PacketTypeInfo(const std::string&, PacketType, bool, int) noexcept;
PacketTypeProperties* data; PacketTypeProperties* data;
bool owns_data = false; bool owns_data = false;
}; };
struct PacketIdManagerData { struct PacketIdManagerData {
PacketIdManagerData(){ PacketIdManagerData(){
memset(this->packetCounter, 0, sizeof(uint32_t) * 16); memset(this->packetCounter, 0, sizeof(uint32_t) * 16);
} }
uint32_t packetCounter[16]{}; uint32_t packetCounter[16]{};
}; };
class PacketIdManager { class PacketIdManager {
public: public:
PacketIdManager() : data(new PacketIdManagerData){} PacketIdManager() : data(new PacketIdManagerData){}
~PacketIdManager() = default; ~PacketIdManager() = default;
PacketIdManager(const PacketIdManager& ref) : data(ref.data) {} PacketIdManager(const PacketIdManager& ref) : data(ref.data) {}
PacketIdManager(PacketIdManager&& ref) : data(std::move(ref.data)) {} PacketIdManager(PacketIdManager&& ref) : data(std::move(ref.data)) {}
uint16_t nextPacketId(const PacketTypeInfo &type){ uint16_t nextPacketId(const PacketTypeInfo &type){
return static_cast<uint16_t>(data->packetCounter[type.type()]++ & 0xFFFF); return static_cast<uint16_t>(data->packetCounter[type.type()]++ & 0xFFFF);
} }
uint16_t currentPacketId(const PacketTypeInfo &type){ uint16_t currentPacketId(const PacketTypeInfo &type){
return static_cast<uint16_t>(data->packetCounter[type.type()] & 0xFFFF); return static_cast<uint16_t>(data->packetCounter[type.type()] & 0xFFFF);
} }
uint16_t generationId(const PacketTypeInfo &type){ uint16_t generationId(const PacketTypeInfo &type){
return static_cast<uint16_t>((data->packetCounter[type.type()] >> 16) & 0xFFFF); return static_cast<uint16_t>((data->packetCounter[type.type()] >> 16) & 0xFFFF);
} }
void reset() { void reset() {
memset(&data->packetCounter[0], 0, sizeof(uint32_t) * 16); memset(&data->packetCounter[0], 0, sizeof(uint32_t) * 16);
} }
private: private:
std::shared_ptr<PacketIdManagerData> data; std::shared_ptr<PacketIdManagerData> data;
}; };
namespace PacketFlag { namespace PacketFlag {
enum PacketFlag : uint8_t { enum PacketFlag : uint8_t {
None = 0x00, None = 0x00,
Fragmented = 0x10, //If packet type voice then its toggle the CELT Mono Fragmented = 0x10, //If packet type voice then its toggle the CELT Mono
NewProtocol = 0x20, NewProtocol = 0x20,
Compressed = 0x40, //If packet type voice than its the header Compressed = 0x40, //If packet type voice than its the header
Unencrypted = 0x80 Unencrypted = 0x80
}; };
typedef uint8_t PacketFlags; typedef uint8_t PacketFlags;
std::string to_string(PacketFlag flag); std::string to_string(PacketFlag flag);
} }
#define MAC_SIZE 8 #define MAC_SIZE 8
#define SERVER_HEADER_SIZE 3 #define SERVER_HEADER_SIZE 3
#define CLIENT_HEADER_SIZE 5 #define CLIENT_HEADER_SIZE 5
class BasicPacket { class BasicPacket {
public: public:
explicit BasicPacket(size_t header_length, size_t data_length); explicit BasicPacket(size_t header_length, size_t data_length);
virtual ~BasicPacket(); virtual ~BasicPacket();
BasicPacket(const BasicPacket&) = delete; BasicPacket(const BasicPacket&) = delete;
BasicPacket(BasicPacket&&) = delete; BasicPacket(BasicPacket&&) = delete;
virtual uint16_t packetId() const = 0; virtual uint16_t packetId() const = 0;
virtual uint16_t generationId() const = 0; virtual uint16_t generationId() const = 0;
virtual PacketTypeInfo type() const = 0; virtual PacketTypeInfo type() const = 0;
/* packet flag info */ /* packet flag info */
inline bool has_flag(PacketFlag::PacketFlag flag) const { return this->_flags_type_byte() & flag; } inline bool has_flag(PacketFlag::PacketFlag flag) const { return this->_flags_type_byte() & flag; }
inline uint8_t flag_mask() const { return this->_flags_type_byte(); }; inline uint8_t flag_mask() const { return this->_flags_type_byte(); };
[[nodiscard]] std::string flags() const; [[nodiscard]] std::string flags() const;
/* manipulate flags */ /* manipulate flags */
inline void set_flags(PacketFlag::PacketFlags flags) { inline void set_flags(PacketFlag::PacketFlags flags) {
uint8_t& byte = this->_flags_type_byte(); uint8_t& byte = this->_flags_type_byte();
byte &= 0xF; /* clear all flags */ byte &= 0xF; /* clear all flags */
byte |= (flags & 0xF0); byte |= (flags & 0xF0);
} }
inline void enable_flag(PacketFlag::PacketFlag flag){ this->toggle_flag(flag, true); } inline void enable_flag(PacketFlag::PacketFlag flag){ this->toggle_flag(flag, true); }
inline void toggle_flag(PacketFlag::PacketFlag flag, bool state) { inline void toggle_flag(PacketFlag::PacketFlag flag, bool state) {
if(state) if(state)
this->_flags_type_byte() |= flag; this->_flags_type_byte() |= flag;
else else
this->_flags_type_byte() &= (uint8_t) ~flag; this->_flags_type_byte() &= (uint8_t) ~flag;
} }
virtual void applyPacketId(PacketIdManager &); virtual void applyPacketId(PacketIdManager &);
virtual void applyPacketId(uint16_t, uint16_t); virtual void applyPacketId(uint16_t, uint16_t);
void setListener(std::unique_ptr<threads::Future<bool>> listener){ void setListener(std::unique_ptr<threads::Future<bool>> listener){
if(!this->type().requireAcknowledge()) if(!this->type().requireAcknowledge())
throw std::logic_error("Packet type does not support a acknowledge listener!"); throw std::logic_error("Packet type does not support a acknowledge listener!");
this->listener = std::move(listener); this->listener = std::move(listener);
} }
inline std::unique_ptr<threads::Future<bool>>& getListener() { return this->listener; } inline std::unique_ptr<threads::Future<bool>>& getListener() { return this->listener; }
inline size_t length() const { return this->_buffer.length(); } inline size_t length() const { return this->_buffer.length(); }
inline const pipes::buffer_view mac() const { return this->_buffer.view(0, MAC_SIZE); } inline const pipes::buffer_view mac() const { return this->_buffer.view(0, MAC_SIZE); }
inline pipes::buffer mac() { return this->_buffer.range(0, MAC_SIZE); } inline pipes::buffer mac() { return this->_buffer.range(0, MAC_SIZE); }
inline size_t mac_length() const { return MAC_SIZE; } inline size_t mac_length() const { return MAC_SIZE; }
inline const pipes::buffer_view header() const { return this->_buffer.view(MAC_SIZE, this->_header_length); } inline const pipes::buffer_view header() const { return this->_buffer.view(MAC_SIZE, this->_header_length); }
inline pipes::buffer header() { return this->_buffer.range(MAC_SIZE, this->_header_length); } inline pipes::buffer header() { return this->_buffer.range(MAC_SIZE, this->_header_length); }
inline size_t header_length() const { return this->_header_length; } inline size_t header_length() const { return this->_header_length; }
inline size_t data_length() const { return this->_buffer.length() - (MAC_SIZE + this->_header_length); } inline size_t data_length() const { return this->_buffer.length() - (MAC_SIZE + this->_header_length); }
inline const pipes::buffer_view data() const { return this->_buffer.view(MAC_SIZE + this->_header_length); } inline const pipes::buffer_view data() const { return this->_buffer.view(MAC_SIZE + this->_header_length); }
inline pipes::buffer data() { return this->_buffer.range(MAC_SIZE + this->_header_length); } inline pipes::buffer data() { return this->_buffer.range(MAC_SIZE + this->_header_length); }
void append_data(const std::vector<pipes::buffer> &data); void append_data(const std::vector<pipes::buffer> &data);
inline void data(const pipes::buffer_view &data){ inline void data(const pipes::buffer_view &data){
this->_buffer.resize(MAC_SIZE + this->_header_length + data.length()); this->_buffer.resize(MAC_SIZE + this->_header_length + data.length());
memcpy((char*) this->_buffer.data_ptr() + MAC_SIZE + this->_header_length, data.data_ptr(), data.length()); memcpy((char*) this->_buffer.data_ptr() + MAC_SIZE + this->_header_length, data.data_ptr(), data.length());
} }
inline void mac(const pipes::buffer_view &_new){ inline void mac(const pipes::buffer_view &_new){
assert(_new.length() >= MAC_SIZE); assert(_new.length() >= MAC_SIZE);
memcpy(this->_buffer.data_ptr(), _new.data_ptr(), MAC_SIZE); memcpy(this->_buffer.data_ptr(), _new.data_ptr(), MAC_SIZE);
} }
[[nodiscard]] inline bool isEncrypted() const { return this->memory_state.encrypted; } [[nodiscard]] inline bool isEncrypted() const { return this->memory_state.encrypted; }
inline void setEncrypted(bool flag){ this->memory_state.encrypted = flag; } inline void setEncrypted(bool flag){ this->memory_state.encrypted = flag; }
[[nodiscard]] inline bool isCompressed() const { return this->memory_state.compressed; } [[nodiscard]] inline bool isCompressed() const { return this->memory_state.compressed; }
inline void setCompressed(bool flag){ this->memory_state.compressed = flag; } inline void setCompressed(bool flag){ this->memory_state.compressed = flag; }
[[nodiscard]] inline bool isFragmentEntry() const { return this->memory_state.fragment_entry; } [[nodiscard]] inline bool isFragmentEntry() const { return this->memory_state.fragment_entry; }
inline void setFragmentedEntry(bool flag){ this->memory_state.fragment_entry = flag; } inline void setFragmentedEntry(bool flag){ this->memory_state.fragment_entry = flag; }
Command asCommand(); Command asCommand();
//Has the size of a byte //Has the size of a byte
union { union {
#ifdef WIN32 #ifdef WIN32
__pragma(pack(push, 1)) __pragma(pack(push, 1))
#endif #endif
struct { struct {
bool encrypted: 1; bool encrypted: 1;
bool compressed: 1; bool compressed: 1;
bool fragment_entry: 1; bool fragment_entry: 1;
bool id_branded: 1; bool id_branded: 1;
} }
#ifdef WIN32 #ifdef WIN32
__pragma(pack(pop)); __pragma(pack(pop));
#else #else
__attribute__((packed)); __attribute__((packed));
#endif #endif
uint8_t flags = 0; uint8_t flags = 0;
} memory_state; } memory_state;
pipes::buffer buffer() { return this->_buffer; } pipes::buffer buffer() { return this->_buffer; }
void buffer(pipes::buffer buffer) { void buffer(pipes::buffer buffer) {
assert(buffer.length() >= this->_header_length + MAC_SIZE); assert(buffer.length() >= this->_header_length + MAC_SIZE);
this->_buffer = std::move(buffer); this->_buffer = std::move(buffer);
} }
protected: protected:
BasicPacket() = default; BasicPacket() = default;
virtual const uint8_t& _flags_type_byte() const = 0; virtual const uint8_t& _flags_type_byte() const = 0;
virtual uint8_t& _flags_type_byte() = 0; virtual uint8_t& _flags_type_byte() = 0;
virtual void setPacketId(uint16_t, uint16_t) = 0; virtual void setPacketId(uint16_t, uint16_t) = 0;
uint8_t _header_length; uint8_t _header_length;
pipes::buffer _buffer; pipes::buffer _buffer;
uint16_t genId = 0; uint16_t genId = 0;
std::unique_ptr<threads::Future<bool>> listener; std::unique_ptr<threads::Future<bool>> listener;
}; };
/** /**
* Packet from the client * Packet from the client
*/ */
class ClientPacket : public BasicPacket { class ClientPacket : public BasicPacket {
friend std::unique_ptr<ClientPacket> std::make_unique<ClientPacket>(); friend std::unique_ptr<ClientPacket> std::make_unique<ClientPacket>();
public: public:
static constexpr size_t META_MAC_SIZE = 8; static constexpr size_t META_MAC_SIZE = 8;
static constexpr size_t META_HEADER_SIZE = CLIENT_HEADER_SIZE; static constexpr size_t META_HEADER_SIZE = CLIENT_HEADER_SIZE;
static constexpr size_t META_SIZE = META_MAC_SIZE + META_HEADER_SIZE; static constexpr size_t META_SIZE = META_MAC_SIZE + META_HEADER_SIZE;
[[nodiscard]] static std::unique_ptr<ClientPacket> from_buffer(const pipes::buffer_view& buffer); [[nodiscard]] static std::unique_ptr<ClientPacket> from_buffer(const pipes::buffer_view& buffer);
ClientPacket(const PacketTypeInfo& type, const pipes::buffer_view& data); ClientPacket(const PacketTypeInfo& type, const pipes::buffer_view& data);
ClientPacket(const PacketTypeInfo& type, uint8_t flag_mask, const pipes::buffer_view& data); ClientPacket(const PacketTypeInfo& type, uint8_t flag_mask, const pipes::buffer_view& data);
~ClientPacket() override; ~ClientPacket() override;
ClientPacket(const ClientPacket&) = delete; ClientPacket(const ClientPacket&) = delete;
ClientPacket(ClientPacket&&) = delete; ClientPacket(ClientPacket&&) = delete;
uint16_t clientId() const; uint16_t clientId() const;
void clientId(uint16_t); void clientId(uint16_t);
uint16_t packetId() const override; uint16_t packetId() const override;
uint16_t generationId() const override; uint16_t generationId() const override;
void generationId(uint16_t generation) { this->genId = generation; } void generationId(uint16_t generation) { this->genId = generation; }
PacketTypeInfo type() const override; PacketTypeInfo type() const override;
void type(const PacketTypeInfo&); void type(const PacketTypeInfo&);
private: private:
ClientPacket() = default; ClientPacket() = default;
const uint8_t &_flags_type_byte() const override { const uint8_t &_flags_type_byte() const override {
return this->header().data_ptr<uint8_t>()[4]; return this->header().data_ptr<uint8_t>()[4];
} }
uint8_t &_flags_type_byte() override { uint8_t &_flags_type_byte() override {
return this->header().data_ptr<uint8_t>()[4]; return this->header().data_ptr<uint8_t>()[4];
} }
void setPacketId(uint16_t, uint16_t) override; void setPacketId(uint16_t, uint16_t) override;
}; };
class ClientPacketParser { class ClientPacketParser {
public: public:
constexpr static auto kHeaderOffset = 8; constexpr static auto kHeaderOffset = 8;
constexpr static auto kHeaderLength = CLIENT_HEADER_SIZE; constexpr static auto kHeaderLength = CLIENT_HEADER_SIZE;
constexpr static auto kPayloadOffset = kHeaderOffset + CLIENT_HEADER_SIZE; constexpr static auto kPayloadOffset = kHeaderOffset + CLIENT_HEADER_SIZE;
explicit ClientPacketParser(pipes::buffer_view buffer) : _buffer{std::move(buffer)} {} explicit ClientPacketParser(pipes::buffer_view buffer) : _buffer{std::move(buffer)} {}
ClientPacketParser(const ClientPacketParser&) = delete; ClientPacketParser(const ClientPacketParser&) = delete;
[[nodiscard]] inline bool valid() const { [[nodiscard]] inline bool valid() const {
if(this->_buffer.length() < kPayloadOffset) return false; if(this->_buffer.length() < kPayloadOffset) return false;
return this->type() <= 8; return this->type() <= 8;
} }
[[nodiscard]] inline const void* data_ptr() const { return this->_buffer.data_ptr(); } [[nodiscard]] inline const void* data_ptr() const { return this->_buffer.data_ptr(); }
[[nodiscard]] inline void* mutable_data_ptr() { return (void*) this->_buffer.data_ptr(); } [[nodiscard]] inline void* mutable_data_ptr() { return (void*) this->_buffer.data_ptr(); }
[[nodiscard]] inline pipes::buffer_view buffer() const { return this->_buffer; } [[nodiscard]] inline pipes::buffer_view buffer() const { return this->_buffer; }
[[nodiscard]] inline pipes::buffer_view mac() const { return this->_buffer.view(0, 8); } [[nodiscard]] inline pipes::buffer_view mac() const { return this->_buffer.view(0, 8); }
[[nodiscard]] inline pipes::buffer_view payload() const { return this->_buffer.view(kPayloadOffset); } [[nodiscard]] inline pipes::buffer_view payload() const { return this->_buffer.view(kPayloadOffset); }
[[nodiscard]] inline size_t payload_length() const { return this->_buffer.length() - kPayloadOffset; } [[nodiscard]] inline size_t payload_length() const { return this->_buffer.length() - kPayloadOffset; }
[[nodiscard]] uint16_t client_id() const; [[nodiscard]] uint16_t client_id() const;
[[nodiscard]] uint16_t packet_id() const; [[nodiscard]] uint16_t packet_id() const;
[[nodiscard]] uint8_t type() const; [[nodiscard]] uint8_t type() const;
[[nodiscard]] uint8_t flags() const; [[nodiscard]] uint8_t flags() const;
[[nodiscard]] bool is_encrypted() const; [[nodiscard]] bool is_encrypted() const;
[[nodiscard]] bool is_compressed() const; [[nodiscard]] bool is_compressed() const;
[[nodiscard]] bool is_fragmented() const; [[nodiscard]] bool is_fragmented() const;
[[nodiscard]] uint16_t estimated_generation() const { return this->generation; } [[nodiscard]] uint16_t estimated_generation() const { return this->generation; }
void set_estimated_generation(uint16_t gen) { this->generation = gen; } void set_estimated_generation(uint16_t gen) { this->generation = gen; }
inline void set_decrypted() { this->decrypted = true; } inline void set_decrypted() { this->decrypted = true; }
inline void set_uncompressed() { this->uncompressed = true; } inline void set_uncompressed() { this->uncompressed = true; }
inline void set_defragmented() { this->defragmented = true; } inline void set_defragmented() { this->defragmented = true; }
private: private:
uint16_t generation{}; uint16_t generation{};
bool decrypted{false}, uncompressed{false}, defragmented{false}; bool decrypted{false}, uncompressed{false}, defragmented{false};
pipes::buffer_view _buffer{}; pipes::buffer_view _buffer{};
}; };
/** /**
* Packet from the server * Packet from the server
*/ */
class ServerPacket : public BasicPacket { class ServerPacket : public BasicPacket {
friend std::unique_ptr<ServerPacket> std::make_unique<ServerPacket>(); friend std::unique_ptr<ServerPacket> std::make_unique<ServerPacket>();
public: public:
static constexpr size_t META_MAC_SIZE = 8; static constexpr size_t META_MAC_SIZE = 8;
static constexpr size_t META_HEADER_SIZE = SERVER_HEADER_SIZE; static constexpr size_t META_HEADER_SIZE = SERVER_HEADER_SIZE;
static constexpr size_t META_SIZE = META_MAC_SIZE + META_HEADER_SIZE; static constexpr size_t META_SIZE = META_MAC_SIZE + META_HEADER_SIZE;
[[nodiscard]] static std::unique_ptr<ServerPacket> from_buffer(const pipes::buffer_view& buffer); [[nodiscard]] static std::unique_ptr<ServerPacket> from_buffer(const pipes::buffer_view& buffer);
ServerPacket(uint8_t flagMask, const pipes::buffer_view& data); ServerPacket(uint8_t flagMask, const pipes::buffer_view& data);
ServerPacket(const PacketTypeInfo& type, const pipes::buffer_view& data); ServerPacket(const PacketTypeInfo& type, const pipes::buffer_view& data);
ServerPacket(PacketTypeInfo type, size_t /* data length */); ServerPacket(PacketTypeInfo type, size_t /* data length */);
~ServerPacket() override; ~ServerPacket() override;
ServerPacket(const ServerPacket&) = delete; ServerPacket(const ServerPacket&) = delete;
ServerPacket(ServerPacket&&) = delete; ServerPacket(ServerPacket&&) = delete;
[[nodiscard]] uint16_t packetId() const override; [[nodiscard]] uint16_t packetId() const override;
[[nodiscard]] uint16_t generationId() const override; [[nodiscard]] uint16_t generationId() const override;
void generationId(uint16_t generation) { this->genId = generation; } void generationId(uint16_t generation) { this->genId = generation; }
[[nodiscard]] PacketTypeInfo type() const override; [[nodiscard]] PacketTypeInfo type() const override;
private: private:
ServerPacket() = default; ServerPacket() = default;
[[nodiscard]] const uint8_t &_flags_type_byte() const override { [[nodiscard]] const uint8_t &_flags_type_byte() const override {
return this->header().data_ptr<uint8_t>()[2]; return this->header().data_ptr<uint8_t>()[2];
} }
uint8_t &_flags_type_byte() override { uint8_t &_flags_type_byte() override {
return this->header().data_ptr<uint8_t>()[2]; return this->header().data_ptr<uint8_t>()[2];
} }
void setPacketId(uint16_t, uint16_t) override; void setPacketId(uint16_t, uint16_t) override;
}; };
} }
} }

View File

@ -1,220 +1,220 @@
#pragma once #pragma once
#ifdef byte #ifdef byte
#define byte asdd #define byte asdd
#ifndef WIN32 #ifndef WIN32
#warning The byte macro is already defined! Undefining it! #warning The byte macro is already defined! Undefining it!
#endif #endif
#undef byte #undef byte
#endif #endif
#include <stdexcept> #include <stdexcept>
#include <string> #include <string>
#include <map> #include <map>
#include <list> #include <list>
#include <deque> #include <deque>
#include <memory> #include <memory>
#include <pipes/buffer.h> #include <pipes/buffer.h>
#include "../Variable.h" #include "../Variable.h"
#ifdef HAVE_JSON #ifdef HAVE_JSON
#include <json/json.h> #include <json/json.h>
#endif #endif
namespace ts { namespace ts {
#define PARM_TYPE(type, fromString, toString) \ #define PARM_TYPE(type, fromString, toString) \
BaseCommandParm(std::string key, type value) : BaseCommandParm(std::pair<std::string, std::string>(key, "")) {\ BaseCommandParm(std::string key, type value) : BaseCommandParm(std::pair<std::string, std::string>(key, "")) {\
toString; \ toString; \
} \ } \
BaseCommandParm& operator=(type value){ \ BaseCommandParm& operator=(type value){ \
toString; \ toString; \
return *this; \ return *this; \
} \ } \
\ \
operator type(){ \ operator type(){ \
fromString; \ fromString; \
} }
class Command; class Command;
class ValueList; class ValueList;
//PARM_TYPE(ts::Property, return ts::Property(nullptr, key(), value(), 0), f_value() = value.value()); //PARM_TYPE(ts::Property, return ts::Property(nullptr, key(), value(), 0), f_value() = value.value());
class ParameterBulk { class ParameterBulk {
friend class Command; friend class Command;
friend class ValueList; friend class ValueList;
public: public:
ParameterBulk(const ParameterBulk& ref) : parms(ref.parms) {} ParameterBulk(const ParameterBulk& ref) : parms(ref.parms) {}
variable operator[](size_t index){ variable operator[](size_t index){
if(parms.size() > index) return parms[index]; if(parms.size() > index) return parms[index];
return variable{"", "", VARTYPE_NULL}; return variable{"", "", VARTYPE_NULL};
} }
const variable& operator[](const std::string& key) const { const variable& operator[](const std::string& key) const {
for(const auto& elm : parms) for(const auto& elm : parms)
if(elm.key() == key){ if(elm.key() == key){
return elm; return elm;
} }
throw std::invalid_argument("could not find key [" + key + "]"); throw std::invalid_argument("could not find key [" + key + "]");
} }
variable& operator[](const std::string& key) { variable& operator[](const std::string& key) {
for(auto& elm : parms) for(auto& elm : parms)
if(elm.key() == key){ if(elm.key() == key){
return elm; return elm;
} }
this->parms.push_back(variable(key, "", VariableType::VARTYPE_NULL)); this->parms.push_back(variable(key, "", VariableType::VARTYPE_NULL));
return this->operator[](key); return this->operator[](key);
} }
bool has(const std::string& key) const { bool has(const std::string& key) const {
for(const auto& elm : parms) for(const auto& elm : parms)
if(elm.key() == key && elm.type() != VariableType::VARTYPE_NULL) return true; if(elm.key() == key && elm.type() != VariableType::VARTYPE_NULL) return true;
return false; return false;
} }
std::deque<std::string> keys() const { std::deque<std::string> keys() const {
std::deque<std::string> result; std::deque<std::string> result;
for(const auto& elm : parms) for(const auto& elm : parms)
result.push_back(elm.key()); result.push_back(elm.key());
return result; return result;
} }
ParameterBulk& operator=(const ParameterBulk& ref){ ParameterBulk& operator=(const ParameterBulk& ref){
parms = ref.parms; parms = ref.parms;
return *this; return *this;
} }
private: private:
ParameterBulk() {} ParameterBulk() {}
ParameterBulk(std::deque<variable> p) : parms(p) {} ParameterBulk(std::deque<variable> p) : parms(p) {}
std::deque<variable> parms; std::deque<variable> parms;
}; };
class ValueList { class ValueList {
friend class Command; friend class Command;
public: public:
ValueList() = delete; ValueList() = delete;
ValueList(const ValueList& ref) : key(ref.key), bulkList(ref.bulkList) {} ValueList(const ValueList& ref) : key(ref.key), bulkList(ref.bulkList) {}
variable operator[](int index){ variable operator[](int index){
while(index >= bulkList.size()) bulkList.push_back(ParameterBulk()); while(index >= bulkList.size()) bulkList.push_back(ParameterBulk());
return bulkList[index][key]; return bulkList[index][key];
} }
variable first() const { variable first() const {
int index = 0; int index = 0;
while(index < bulkList.size() && !bulkList[index].has(key)) index++; while(index < bulkList.size() && !bulkList[index].has(key)) index++;
if(index < bulkList.size()) return bulkList[index][key]; if(index < bulkList.size()) return bulkList[index][key];
return variable{this->key, "", VariableType::VARTYPE_NULL}; return variable{this->key, "", VariableType::VARTYPE_NULL};
throw std::invalid_argument("could not find key [" + key + "]"); throw std::invalid_argument("could not find key [" + key + "]");
} }
size_t size(){ size_t size(){
size_t count = 0; size_t count = 0;
for(const auto& blk : this->bulkList) for(const auto& blk : this->bulkList)
if(blk.has(this->key)) count++; if(blk.has(this->key)) count++;
return count; return count;
} }
template <typename T> template <typename T>
ValueList& operator=(T var){ operator[](0) = var; return *this; } ValueList& operator=(T var){ operator[](0) = var; return *this; }
ValueList& operator=(ts::ValueList& var){ operator[](0) = var.first().value(); return *this; } ValueList& operator=(ts::ValueList& var){ operator[](0) = var.first().value(); return *this; }
template <typename T> template <typename T>
T as() const { return first().as<T>(); } T as() const { return first().as<T>(); }
template <typename T> template <typename T>
operator T() { return as<T>(); } operator T() { return as<T>(); }
template <typename T> template <typename T>
bool operator==(T other){ return as<T>() == other; } bool operator==(T other){ return as<T>() == other; }
template <typename T> template <typename T>
bool operator!=(T other){ return as<T>() != other; } bool operator!=(T other){ return as<T>() != other; }
std::string string() const { return as<std::string>(); } std::string string() const { return as<std::string>(); }
friend std::ostream& operator<<(std::ostream&, const ValueList&); friend std::ostream& operator<<(std::ostream&, const ValueList&);
private: private:
ValueList(std::string& key, std::deque<ParameterBulk>& bulkList) : key(key), bulkList(bulkList) {} ValueList(std::string& key, std::deque<ParameterBulk>& bulkList) : key(key), bulkList(bulkList) {}
std::string key; std::string key;
public: public:
std::deque<ParameterBulk>& bulkList; std::deque<ParameterBulk>& bulkList;
}; };
inline std::ostream& operator<<(std::ostream& stream,const ValueList& list) { inline std::ostream& operator<<(std::ostream& stream,const ValueList& list) {
stream << "{ Key: " << list.key << " = ["; stream << "{ Key: " << list.key << " = [";
for(auto it = list.bulkList.begin(); it != list.bulkList.end(); it++) for(auto it = list.bulkList.begin(); it != list.bulkList.end(); it++)
if(it->has(list.key)) { if(it->has(list.key)) {
stream << (*it)[list.key].value(); stream << (*it)[list.key].value();
if(it + 1 != list.bulkList.end()) if(it + 1 != list.bulkList.end())
stream << ", "; stream << ", ";
} }
stream << "]}"; stream << "]}";
return stream; return stream;
} }
class Command { class Command {
public: public:
static Command parse(const pipes::buffer_view& buffer, bool expect_command = true, bool drop_non_utf8 = false); static Command parse(const pipes::buffer_view& buffer, bool expect_command = true, bool drop_non_utf8 = false);
explicit Command(const std::string& command); explicit Command(const std::string& command);
explicit Command(const std::string& command, std::initializer_list<variable>); explicit Command(const std::string& command, std::initializer_list<variable>);
explicit Command(const std::string& command, std::initializer_list<std::initializer_list<variable>>); explicit Command(const std::string& command, std::initializer_list<std::initializer_list<variable>>);
Command(const Command&); Command(const Command&);
~Command(); ~Command();
inline std::string command() const { return getCommand(); } inline std::string command() const { return getCommand(); }
std::string getCommand() const { return _command; } std::string getCommand() const { return _command; }
std::string build(bool escaped = true) const; std::string build(bool escaped = true) const;
#ifdef HAVE_JSON #ifdef HAVE_JSON
Json::Value buildJson() const; Json::Value buildJson() const;
#endif #endif
const ParameterBulk& operator[](size_t index) const { const ParameterBulk& operator[](size_t index) const {
if(bulks.size() <= index) throw std::invalid_argument("got out of length"); if(bulks.size() <= index) throw std::invalid_argument("got out of length");
return bulks[index]; return bulks[index];
} }
ParameterBulk& operator[](size_t index){ ParameterBulk& operator[](size_t index){
while(bulks.size() <= index) bulks.push_back(ParameterBulk{}); while(bulks.size() <= index) bulks.push_back(ParameterBulk{});
return bulks[index]; return bulks[index];
} }
ValueList operator[](std::string key){ ValueList operator[](std::string key){
return ValueList(key, bulks); return ValueList(key, bulks);
} }
size_t bulkCount() const { return bulks.size(); } size_t bulkCount() const { return bulks.size(); }
void pop_bulk(); void pop_bulk();
void push_bulk_front(); void push_bulk_front();
bool hasParm(std::string); bool hasParm(std::string);
void clear_parameters() { this->paramethers.clear(); } void clear_parameters() { this->paramethers.clear(); }
std::deque<std::string> parms(); std::deque<std::string> parms();
void enableParm(const std::string& key){ toggleParm(key, true); } void enableParm(const std::string& key){ toggleParm(key, true); }
void disableParm(const std::string& key){ toggleParm(key, false); } void disableParm(const std::string& key){ toggleParm(key, false); }
void toggleParm(const std::string& key, bool flag); void toggleParm(const std::string& key, bool flag);
void reverseBulks(); void reverseBulks();
private: private:
Command(); Command();
std::string _command; std::string _command;
std::deque<ParameterBulk> bulks; std::deque<ParameterBulk> bulks;
std::deque<std::string> paramethers; std::deque<std::string> paramethers;
}; };
} }
DEFINE_VARIABLE_TRANSFORM_TO_STR(ts::ValueList, in.string()); DEFINE_VARIABLE_TRANSFORM_TO_STR(ts::ValueList, in.string());
DEFINE_VARIABLE_TRANSFORM_TYPE(ts::ValueList, VARTYPE_TEXT); DEFINE_VARIABLE_TRANSFORM_TYPE(ts::ValueList, VARTYPE_TEXT);
#undef PARM_TYPE #undef PARM_TYPE

File diff suppressed because it is too large Load Diff

View File

@ -1,74 +1,74 @@
#pragma once #pragma once
#include <stdexcept> #include <stdexcept>
#include <string> #include <string>
#include <memory> #include <memory>
#include <condition_variable> #include <condition_variable>
#include "sql/SqlQuery.h" #include "sql/SqlQuery.h"
#include "../../misc/spin_lock.h" #include "../../misc/spin_lock.h"
#include <mysql.h> #include <mysql.h>
#define ERROR_MYSQL_MISSING_DRIVER -1 #define ERROR_MYSQL_MISSING_DRIVER -1
#define ERROR_MYSQL_INVLID_CONNECT -2 #define ERROR_MYSQL_INVLID_CONNECT -2
#define ERROR_MYSQL_INVLID_PROPERTIES -3 #define ERROR_MYSQL_INVLID_PROPERTIES -3
#define ERROR_MYSQL_INVLID_URL -4 #define ERROR_MYSQL_INVLID_URL -4
namespace sql::mysql { namespace sql::mysql {
class MySQLManager; class MySQLManager;
bool evaluate_sql_query(std::string& sql, const std::vector<variable>& vars, std::vector<variable>& result); bool evaluate_sql_query(std::string& sql, const std::vector<variable>& vars, std::vector<variable>& result);
class MySQLCommand : public CommandData { }; class MySQLCommand : public CommandData { };
struct Connection { struct Connection {
MYSQL* handle = nullptr; MYSQL* handle = nullptr;
spin_lock used_lock; spin_lock used_lock;
bool used = false; bool used = false;
~Connection(); ~Connection();
}; };
struct AcquiredConnection { struct AcquiredConnection {
MySQLManager* owner; MySQLManager* owner;
std::shared_ptr<Connection> connection; std::shared_ptr<Connection> connection;
AcquiredConnection(MySQLManager* owner, std::shared_ptr<Connection> ); AcquiredConnection(MySQLManager* owner, std::shared_ptr<Connection> );
~AcquiredConnection(); ~AcquiredConnection();
}; };
class MySQLManager : public SqlManager { class MySQLManager : public SqlManager {
friend struct AcquiredConnection; friend struct AcquiredConnection;
public: public:
//typedef std::function<void(const std::shared_ptr<ConnectionEntry>&)> ListenerConnectionDisconnect; //typedef std::function<void(const std::shared_ptr<ConnectionEntry>&)> ListenerConnectionDisconnect;
//typedef std::function<void(const std::shared_ptr<ConnectionEntry>&)> ListenerConnectionCreated; //typedef std::function<void(const std::shared_ptr<ConnectionEntry>&)> ListenerConnectionCreated;
typedef std::function<void()> ListenerConnected; typedef std::function<void()> ListenerConnected;
typedef std::function<void(bool /* wanted */)> ListenerDisconnected; typedef std::function<void(bool /* wanted */)> ListenerDisconnected;
MySQLManager(); MySQLManager();
virtual ~MySQLManager(); virtual ~MySQLManager();
result connect(const std::string &string) override; result connect(const std::string &string) override;
bool connected() override; bool connected() override;
result disconnect() override; result disconnect() override;
ListenerDisconnected listener_disconnected; ListenerDisconnected listener_disconnected;
protected: protected:
std::shared_ptr<CommandData> copyCommandData(std::shared_ptr<CommandData> ptr) override; std::shared_ptr<CommandData> copyCommandData(std::shared_ptr<CommandData> ptr) override;
std::shared_ptr<CommandData> allocateCommandData() override; std::shared_ptr<CommandData> allocateCommandData() override;
result executeCommand(std::shared_ptr<CommandData> ptr) override; result executeCommand(std::shared_ptr<CommandData> ptr) override;
result queryCommand(std::shared_ptr<CommandData> ptr, const QueryCallback &fn) override; result queryCommand(std::shared_ptr<CommandData> ptr, const QueryCallback &fn) override;
public: public:
std::unique_ptr<AcquiredConnection> next_connection(); std::unique_ptr<AcquiredConnection> next_connection();
void connection_closed(const std::shared_ptr<Connection>& /* connection */); void connection_closed(const std::shared_ptr<Connection>& /* connection */);
std::mutex connections_lock; std::mutex connections_lock;
std::condition_variable connections_condition; std::condition_variable connections_condition;
std::deque<std::shared_ptr<Connection>> connections; std::deque<std::shared_ptr<Connection>> connections;
bool disconnecting = false; bool disconnecting = false;
}; };
} }