diff --git a/CMakeLists.txt b/CMakeLists.txt index 3d465b9..28484a4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,254 +3,254 @@ project(TeaSpeak-Shared) set(CMAKE_CXX_STANDARD 17) 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_INCLUDE_CURRENT_DIR ON) + 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) else() - #For Windows - add_definitions(-D_SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING) + #For Windows + 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() if(CMAKE_PLATFORM_INCLUDE AND NOT CMAKE_PLATFORM_INCLUDE STREQUAL "") - include(${CMAKE_PLATFORM_INCLUDE}) + include(${CMAKE_PLATFORM_INCLUDE}) endif() if(NOT TEASPEAK_SERVER) - find_package(TomMath REQUIRED) - include_directories(${TomMath_INCLUDE_DIR}) + find_package(TomMath REQUIRED) + include_directories(${TomMath_INCLUDE_DIR}) - find_package(TomCrypt REQUIRED) - include_directories(${TomCrypt_INCLUDE_DIR}) + find_package(TomCrypt REQUIRED) + include_directories(${TomCrypt_INCLUDE_DIR}) - find_package(DataPipes REQUIRED) - include_directories(${DataPipes_INCLUDE_DIR}) - message("Include: ${DataPipes_INCLUDE_DIR}") + find_package(DataPipes REQUIRED) + include_directories(${DataPipes_INCLUDE_DIR}) + message("Include: ${DataPipes_INCLUDE_DIR}") - find_package(Libevent REQUIRED) - include_directories(${LIBEVENT_INCLUDE_DIRS}) + find_package(Libevent REQUIRED) + include_directories(${LIBEVENT_INCLUDE_DIRS}) - find_package(StringVariable REQUIRED) - include_directories(${StringVariable_INCLUDE_DIR}) + find_package(StringVariable REQUIRED) + include_directories(${StringVariable_INCLUDE_DIR}) - find_package(Ed25519 REQUIRED) - include_directories(${ed25519_INCLUDE_DIR}) + find_package(Ed25519 REQUIRED) + include_directories(${ed25519_INCLUDE_DIR}) - find_package(ThreadPool REQUIRED) - include_directories(${ThreadPool_INCLUDE_DIR}) - if(WIN32) - add_definitions(-DWINDOWS) #Required for ThreadPool - endif() - find_package(spdlog REQUIRED) - link_libraries(spdlog::spdlog_header_only) #Its a header only lib so we should be fine :) + find_package(ThreadPool REQUIRED) + include_directories(${ThreadPool_INCLUDE_DIR}) + if(WIN32) + add_definitions(-DWINDOWS) #Required for ThreadPool + endif() + find_package(spdlog REQUIRED) + link_libraries(spdlog::spdlog_header_only) #Its a header only lib so we should be fine :) - add_definitions(-DNO_OPEN_SSL) - add_definitions(-D_HAS_STD_BYTE) - #FML + add_definitions(-DNO_OPEN_SSL) + add_definitions(-D_HAS_STD_BYTE) + #FML else() - add_definitions(-DHAVE_CXX_TERMINAL) - add_definitions(-DHAVE_JSON) - set(HAVE_SQLITE3 ON) - set(HAVE_OPEN_SSL ON) - message("HAVE JSON!") + add_definitions(-DHAVE_CXX_TERMINAL) + add_definitions(-DHAVE_JSON) + set(HAVE_SQLITE3 ON) + set(HAVE_OPEN_SSL ON) + message("HAVE JSON!") endif() if (MSVC) - set(CompilerFlags - CMAKE_CXX_FLAGS - CMAKE_CXX_FLAGS_DEBUG - CMAKE_CXX_FLAGS_RELEASE - CMAKE_C_FLAGS - CMAKE_C_FLAGS_DEBUG - CMAKE_C_FLAGS_RELEASE - ) - foreach(CompilerFlag ${CompilerFlags}) - string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}") - endforeach() - add_compile_options("/EHsc") #We require exception handling + set(CompilerFlags + CMAKE_CXX_FLAGS + CMAKE_CXX_FLAGS_DEBUG + CMAKE_CXX_FLAGS_RELEASE + CMAKE_C_FLAGS + CMAKE_C_FLAGS_DEBUG + CMAKE_C_FLAGS_RELEASE + ) + foreach(CompilerFlag ${CompilerFlags}) + string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}") + endforeach() + add_compile_options("/EHsc") #We require exception handling else() - set(CMAKE_CXX_FLAGS_RELEASE "-O3") #-DNDEBUG We want assert! + set(CMAKE_CXX_FLAGS_RELEASE "-O3") #-DNDEBUG We want assert! endif() add_definitions(-DUSE_BORINGSSL) include_directories(${LIBRARY_PATH}/boringssl/include/) set(SOURCE_FILES - src/misc/rnd.cpp - src/misc/time.cpp - src/misc/memtracker.cpp - src/misc/digest.cpp - src/misc/base64.cpp + src/misc/rnd.cpp + src/misc/time.cpp + src/misc/memtracker.cpp + src/misc/digest.cpp + src/misc/base64.cpp - #Logger - src/log/LogUtils.cpp - src/log/LogSinks.cpp + #Logger + src/log/LogUtils.cpp + src/log/LogSinks.cpp - src/qlz/QuickLZ.cpp - src/qlz/QuickLZ_L3.cpp - src/qlz/QuickLZ_L1.cpp + src/qlz/QuickLZ.cpp + src/qlz/QuickLZ_L3.cpp + src/qlz/QuickLZ_L1.cpp - src/query/command2.cpp - src/query/Command.cpp - src/query/escape.cpp + src/query/command2.cpp + src/query/Command.cpp + src/query/escape.cpp - src/protocol/Packet.cpp - src/protocol/buffers.cpp - src/protocol/buffers_allocator_c.cpp - src/PermissionManager.cpp - src/Properties.cpp - src/BasicChannel.cpp - src/Error.cpp - src/protocol/CryptionHandler.cpp - src/protocol/CompressionHandler.cpp - src/Variable.cpp - src/linked_helper.cpp - src/EventLoop.cpp + src/protocol/Packet.cpp + src/protocol/buffers.cpp + src/protocol/buffers_allocator_c.cpp + src/PermissionManager.cpp + src/Properties.cpp + src/BasicChannel.cpp + src/Error.cpp + src/protocol/CryptionHandler.cpp + src/protocol/CompressionHandler.cpp + src/Variable.cpp + src/linked_helper.cpp + src/EventLoop.cpp - src/License.cpp + src/License.cpp - src/bbcode/bbcodes.cpp + src/bbcode/bbcodes.cpp - src/channel/TreeView.cpp - src/protocol/ringbuffer.cpp - src/protocol/AcknowledgeManager.cpp + src/channel/TreeView.cpp + src/protocol/ringbuffer.cpp + src/protocol/AcknowledgeManager.cpp ) set(HEADER_FILES - src/misc/base64.h - src/misc/endianness.h - src/misc/cast.h - src/misc/rnd.h - src/misc/time.h - src/misc/std_unique_ptr.h - src/misc/net.h - src/misc/lambda.h - src/misc/hex.h - src/misc/advanced_mutex.h - src/misc/memtracker.h - src/misc/strobf.h + src/misc/base64.h + src/misc/endianness.h + src/misc/cast.h + src/misc/rnd.h + src/misc/time.h + src/misc/std_unique_ptr.h + src/misc/net.h + src/misc/lambda.h + src/misc/hex.h + src/misc/advanced_mutex.h + src/misc/memtracker.h + src/misc/strobf.h - src/log/translation.h - src/log/LogUtils.h + src/log/translation.h + src/log/LogUtils.h - src/PermissionManager.h - src/protocol/buffers.h - src/protocol/Packet.h - src/Properties.h - src/BasicChannel.h - src/Definitions.h - src/Error.h - src/protocol/CryptionHandler.h - src/Variable.h - src/misc/queue.h + src/PermissionManager.h + src/protocol/buffers.h + src/protocol/Packet.h + src/Properties.h + src/BasicChannel.h + src/Definitions.h + src/Error.h + src/protocol/CryptionHandler.h + src/Variable.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 ) if(HAVE_SQLITE3) - set(SOURCE_FILES ${SOURCE_FILES} - src/sql/SqlQuery.cpp - src/sql/sqlite/SqliteSQL.cpp - src/sql/mysql/MySQL.cpp - ) - set(HEADER_FILES ${HEADER_FILES} - src/sql/SqlQuery.h - src/sql/sqlite/SqliteSQL.h - src/sql/mysql/MySQL.h - ) + set(SOURCE_FILES ${SOURCE_FILES} + src/sql/SqlQuery.cpp + src/sql/sqlite/SqliteSQL.cpp + src/sql/mysql/MySQL.cpp + ) + set(HEADER_FILES ${HEADER_FILES} + src/sql/SqlQuery.h + src/sql/sqlite/SqliteSQL.h + src/sql/mysql/MySQL.h + ) endif() if(HAVE_OPEN_SSL) - set(SOURCE_FILES ${SOURCE_FILES} - src/ssl/SSLManager.cpp - ) - set(HEADER_FILES ${HEADER_FILES} - src/ssl/SSLManager.h - ) + set(SOURCE_FILES ${SOURCE_FILES} + src/ssl/SSLManager.cpp + ) + set(HEADER_FILES ${HEADER_FILES} + src/ssl/SSLManager.h + ) endif() if (NOT WIN32) - #TODO: Do we really need that anymroe? - set(SOURCE_FILES ${SOURCE_FILES} - #src/misc/TraceUtils.cpp - ) - set(HEADER_FILES ${HEADER_FILES} + #TODO: Do we really need that anymroe? + set(SOURCE_FILES ${SOURCE_FILES} + #src/misc/TraceUtils.cpp + ) + set(HEADER_FILES ${HEADER_FILES} - ) + ) endif () add_library(TeaSpeak STATIC ${SOURCE_FILES} ${HEADER_FILES}) install(TARGETS TeaSpeak - ARCHIVE DESTINATION lib + ARCHIVE DESTINATION lib ) INSTALL ( - DIRECTORY ${CMAKE_SOURCE_DIR}/src/ - DESTINATION include - FILES_MATCHING PATTERN "*.h*" + DIRECTORY ${CMAKE_SOURCE_DIR}/src/ + DESTINATION include + FILES_MATCHING PATTERN "*.h*" ) set(TEST_LIBRARIES - sqlite3 - ${LIBRARY_PATH_THREAD_POOL} #Static - ${LIBRARY_PATH_TERMINAL} #Static - ${LIBRARY_PATH_VARIBALES} - ${LIBRARY_PATH_YAML} - pthread - stdc++fs - ${TOM_LIBRARIES} + sqlite3 + ${LIBRARY_PATH_THREAD_POOL} #Static + ${LIBRARY_PATH_TERMINAL} #Static + ${LIBRARY_PATH_VARIBALES} + ${LIBRARY_PATH_YAML} + pthread + stdc++fs + ${TOM_LIBRARIES} ${LIBEVENT_PATH}/libevent.a ${LIBEVENT_PATH}/libevent_pthreads.a - ${LIBRARY_PATH_ED255} - ${LIBRARY_PATH_JSON} - ${LIBRARY_TOM_CRYPT} - mysqlclient.a + ${LIBRARY_PATH_ED255} + ${LIBRARY_PATH_JSON} + ${LIBRARY_TOM_CRYPT} + mysqlclient.a - ${LIBRARY_PATH_DATA_PIPES} - ${LIBRARY_PATH_BORINGSSL_SSL} - ${LIBRARY_PATH_BORINGSSL_CRYPTO} #Crypto must be linked after - dl - z + ${LIBRARY_PATH_DATA_PIPES} + ${LIBRARY_PATH_BORINGSSL_SSL} + ${LIBRARY_PATH_BORINGSSL_CRYPTO} #Crypto must be linked after + dl + z ) include_directories(src/) option(BUILD_TESTS "Enable/disable test building" ON) if(BUILD_TESTS) - add_executable(RingTest test/RingTest.cpp ${SOURCE_FILES}) - target_link_libraries(RingTest ${TEST_LIBRARIES}) + add_executable(RingTest test/RingTest.cpp ${SOURCE_FILES}) + target_link_libraries(RingTest ${TEST_LIBRARIES}) - if(NOT WIN32) - add_executable(CommandTest ${SOURCE_FILES} ${HEADER_FILES} test/CommandTest.cpp src/log/LogSinks.cpp src/log/LogSinks.h) - target_link_libraries(CommandTest ${TEST_LIBRARIES}) + if(NOT WIN32) + add_executable(CommandTest ${SOURCE_FILES} ${HEADER_FILES} test/CommandTest.cpp src/log/LogSinks.cpp src/log/LogSinks.h) + target_link_libraries(CommandTest ${TEST_LIBRARIES}) - add_executable(WebsocketTest ${SOURCE_FILES} ${HEADER_FILES} test/WSSTest.cpp src/log/LogSinks.cpp src/log/LogSinks.h) - target_link_libraries(WebsocketTest ${TEST_LIBRARIES}) + add_executable(WebsocketTest ${SOURCE_FILES} ${HEADER_FILES} test/WSSTest.cpp src/log/LogSinks.cpp src/log/LogSinks.h) + target_link_libraries(WebsocketTest ${TEST_LIBRARIES}) - add_executable(SQLTest ${SOURCE_FILES} ${HEADER_FILES} test/SQLTest.cpp src/log/LogSinks.cpp src/log/LogSinks.h) - target_link_libraries(SQLTest ${TEST_LIBRARIES}) + add_executable(SQLTest ${SOURCE_FILES} ${HEADER_FILES} test/SQLTest.cpp src/log/LogSinks.cpp src/log/LogSinks.h) + target_link_libraries(SQLTest ${TEST_LIBRARIES}) - add_executable(ChannelTest ${SOURCE_FILES} ${HEADER_FILES} test/ChannelTest.cpp src/log/LogSinks.cpp src/log/LogSinks.h) - target_link_libraries(ChannelTest ${TEST_LIBRARIES}) + add_executable(ChannelTest ${SOURCE_FILES} ${HEADER_FILES} test/ChannelTest.cpp src/log/LogSinks.cpp src/log/LogSinks.h) + target_link_libraries(ChannelTest ${TEST_LIBRARIES}) - add_executable(EndianessTest ${SOURCE_FILES} ${HEADER_FILES} test/EndianessTest.cpp src/log/LogSinks.cpp src/log/LogSinks.h) - target_link_libraries(EndianessTest ${TEST_LIBRARIES}) + add_executable(EndianessTest ${SOURCE_FILES} ${HEADER_FILES} test/EndianessTest.cpp src/log/LogSinks.cpp src/log/LogSinks.h) + target_link_libraries(EndianessTest ${TEST_LIBRARIES}) - include_directories(/usr/local/include/breakpad) - add_executable(CrashTest test/CrashTest.cpp ${SOURCE_FILES}) - target_link_libraries(CrashTest ${TEST_LIBRARIES}) + include_directories(/usr/local/include/breakpad) + add_executable(CrashTest test/CrashTest.cpp ${SOURCE_FILES}) + target_link_libraries(CrashTest ${TEST_LIBRARIES}) - add_executable(PorpertyTest test/PropertyTest.cpp ${SOURCE_FILES}) - target_link_libraries(PorpertyTest ${TEST_LIBRARIES}) + add_executable(PorpertyTest test/PropertyTest.cpp ${SOURCE_FILES}) + target_link_libraries(PorpertyTest ${TEST_LIBRARIES}) - add_executable(BBTest test/BBTest.cpp ${SOURCE_FILES}) - target_link_libraries(BBTest ${TEST_LIBRARIES}) + add_executable(BBTest test/BBTest.cpp ${SOURCE_FILES}) + target_link_libraries(BBTest ${TEST_LIBRARIES}) - add_executable(LinkedTest test/LinkedTest.cpp ${SOURCE_FILES}) - target_link_libraries(LinkedTest ${TEST_LIBRARIES}) + add_executable(LinkedTest test/LinkedTest.cpp ${SOURCE_FILES}) + target_link_libraries(LinkedTest ${TEST_LIBRARIES}) - add_executable(PermissionTest test/PermissionTest.cpp ${SOURCE_FILES}) - target_link_libraries(PermissionTest ${TEST_LIBRARIES}) - endif() + add_executable(PermissionTest test/PermissionTest.cpp ${SOURCE_FILES}) + target_link_libraries(PermissionTest ${TEST_LIBRARIES}) + endif() endif() diff --git a/src/BasicChannel.cpp b/src/BasicChannel.cpp index 59652e1..84dbbda 100644 --- a/src/BasicChannel.cpp +++ b/src/BasicChannel.cpp @@ -14,81 +14,81 @@ using namespace std::chrono; using namespace ts; BasicChannel::BasicChannel(ChannelId parentId, ChannelId channelId) { - this->setProperties(make_shared()); + this->setProperties(make_shared()); - this->_properties->register_property_type(); - this->properties()[property::CHANNEL_ID] = channelId; - this->properties()[property::CHANNEL_PID] = parentId; + this->_properties->register_property_type(); + this->properties()[property::CHANNEL_ID] = channelId; + this->properties()[property::CHANNEL_PID] = parentId; } void BasicChannel::setPermissionManager(const std::shared_ptr& manager) { - this->_permissions = manager; - this->update_properties_from_permissions(); + this->_permissions = manager; + this->update_properties_from_permissions(); } void BasicChannel::setProperties(const std::shared_ptr& props) { - if(this->_properties) { - (*props)[property::CHANNEL_ID] = this->channelId(); - (*props)[property::CHANNEL_PID] = this->properties()[property::CHANNEL_PID].value(); - } - this->_properties = props; + if(this->_properties) { + (*props)[property::CHANNEL_ID] = this->channelId(); + (*props)[property::CHANNEL_PID] = this->properties()[property::CHANNEL_PID].value(); + } + this->_properties = props; - this->properties().registerNotifyHandler([&](Property& prop){ - if(prop.type() == property::CHANNEL_FLAG_DEFAULT) - this->properties()[property::CHANNEL_FLAG_PASSWORD] = false; - else if(prop.type() == property::CHANNEL_ID) - this->_channel_id = prop; - else if(prop.type() == property::CHANNEL_ORDER) - this->_channel_order = prop; - }); + this->properties().registerNotifyHandler([&](Property& prop){ + if(prop.type() == property::CHANNEL_FLAG_DEFAULT) + this->properties()[property::CHANNEL_FLAG_PASSWORD] = false; + else if(prop.type() == property::CHANNEL_ID) + this->_channel_id = prop; + else if(prop.type() == property::CHANNEL_ORDER) + this->_channel_order = prop; + }); - //Update cached variables - if(props->has(property::CHANNEL_ORDER)) this->_channel_order = this->properties()[property::CHANNEL_ORDER]; - else this->_channel_order = 0; - this->_channel_id = this->channelId(); + //Update cached variables + if(props->has(property::CHANNEL_ORDER)) this->_channel_order = this->properties()[property::CHANNEL_ORDER]; + else this->_channel_order = 0; + this->_channel_id = this->channelId(); } std::vector BasicChannel::update_properties_from_permissions() { - std::vector result; - result.reserve(2); + std::vector result; + result.reserve(2); - auto permission_manager = this->permissions(); /* keeps the manager until we've finished our calculations */ - /* update the icon id */ - { - IconId target_icon_id = 0; - auto& permission_icon_flags = permission_manager->permission_flags(permission::i_icon_id); - if(permission_icon_flags.value_set) - target_icon_id = (IconId) permission_manager->permission_values(permission::i_icon_id).value; - if(this->properties()[property::CHANNEL_ICON_ID] != target_icon_id) { - this->properties()[property::CHANNEL_ICON_ID] = target_icon_id; - result.push_back(property::CHANNEL_ICON_ID); - } - } - /* update the channel talk power */ - { - permission::PermissionValue talk_power = 0; - auto& permission_tp_flags = permission_manager->permission_flags(permission::i_client_needed_talk_power); - if(permission_tp_flags.value_set) - talk_power = (IconId) permission_manager->permission_values(permission::i_client_needed_talk_power).value; - if(this->properties()[property::CHANNEL_NEEDED_TALK_POWER] != talk_power) { - this->properties()[property::CHANNEL_NEEDED_TALK_POWER] = talk_power; - result.push_back(property::CHANNEL_NEEDED_TALK_POWER); - } - } + auto permission_manager = this->permissions(); /* keeps the manager until we've finished our calculations */ + /* update the icon id */ + { + IconId target_icon_id = 0; + auto& permission_icon_flags = permission_manager->permission_flags(permission::i_icon_id); + if(permission_icon_flags.value_set) + target_icon_id = (IconId) permission_manager->permission_values(permission::i_icon_id).value; + if(this->properties()[property::CHANNEL_ICON_ID] != target_icon_id) { + this->properties()[property::CHANNEL_ICON_ID] = target_icon_id; + result.push_back(property::CHANNEL_ICON_ID); + } + } + /* update the channel talk power */ + { + permission::PermissionValue talk_power = 0; + auto& permission_tp_flags = permission_manager->permission_flags(permission::i_client_needed_talk_power); + if(permission_tp_flags.value_set) + talk_power = (IconId) permission_manager->permission_values(permission::i_client_needed_talk_power).value; + if(this->properties()[property::CHANNEL_NEEDED_TALK_POWER] != talk_power) { + this->properties()[property::CHANNEL_NEEDED_TALK_POWER] = talk_power; + result.push_back(property::CHANNEL_NEEDED_TALK_POWER); + } + } - return result; + return result; } std::shared_ptr BasicChannel::parent() { - auto link_lock = this->_link.lock(); - if(!link_lock) - return nullptr; + auto link_lock = this->_link.lock(); + if(!link_lock) + return nullptr; - auto parent_lock = link_lock->parent.lock(); - if(!parent_lock) - return nullptr; + auto parent_lock = link_lock->parent.lock(); + if(!parent_lock) + return nullptr; - return dynamic_pointer_cast(parent_lock->entry); + return dynamic_pointer_cast(parent_lock->entry); } BasicChannel::BasicChannel(std::shared_ptr parent, ChannelId channelId) : BasicChannel(parent ? parent->channelId() : 0, channelId) { } @@ -96,9 +96,9 @@ BasicChannel::BasicChannel(std::shared_ptr parent, ChannelId chann BasicChannel::~BasicChannel() { } ChannelType::ChannelType BasicChannel::channelType() { - if (this->properties()[property::CHANNEL_FLAG_PERMANENT].as()) return ChannelType::ChannelType::permanent; - else if (this->properties()[property::CHANNEL_FLAG_SEMI_PERMANENT].as()) return ChannelType::ChannelType::semipermanent; - else return ChannelType::ChannelType::temporary; + if (this->properties()[property::CHANNEL_FLAG_PERMANENT].as()) return ChannelType::ChannelType::permanent; + else if (this->properties()[property::CHANNEL_FLAG_SEMI_PERMANENT].as()) return ChannelType::ChannelType::semipermanent; + else return ChannelType::ChannelType::temporary; } void BasicChannel::setChannelType(ChannelType::ChannelType type) { @@ -107,35 +107,35 @@ void BasicChannel::setChannelType(ChannelType::ChannelType type) { } bool BasicChannel::passwordMatch(std::string password, bool hashed) { - if (!this->properties()[property::CHANNEL_FLAG_PASSWORD].as() || this->properties()[property::CHANNEL_PASSWORD].value().empty()) return true; - if (password.empty()) return false; + if (!this->properties()[property::CHANNEL_FLAG_PASSWORD].as() || this->properties()[property::CHANNEL_PASSWORD].value().empty()) return true; + if (password.empty()) return false; - if(this->properties()[property::CHANNEL_PASSWORD].as() == password) - return true; + if(this->properties()[property::CHANNEL_PASSWORD].as() == password) + return true; - password = base64::encode(digest::sha1(password)); - return this->properties()[property::CHANNEL_PASSWORD].as() == password; + password = base64::encode(digest::sha1(password)); + return this->properties()[property::CHANNEL_PASSWORD].as() == password; } int64_t BasicChannel::emptySince() { - if (!properties().hasProperty(property::CHANNEL_LAST_LEFT)) - return 0; + if (!properties().hasProperty(property::CHANNEL_LAST_LEFT)) + return 0; - time_point lastLeft = time_point() + milliseconds(properties()[property::CHANNEL_LAST_LEFT].as()); - return (int64_t) duration_cast(system_clock::now() - lastLeft).count(); + time_point lastLeft = time_point() + milliseconds(properties()[property::CHANNEL_LAST_LEFT].as()); + return (int64_t) duration_cast(system_clock::now() - lastLeft).count(); } void BasicChannel::setLinkedHandle(const std::weak_ptr &ptr) { - TreeEntry::setLinkedHandle(ptr); - this->_link = ptr; + TreeEntry::setLinkedHandle(ptr); + this->_link = ptr; } ChannelId BasicChannel::channelId() const { - return this->_channel_id; + return this->_channel_id; } ChannelId BasicChannel::previousChannelId() const { - return this->_channel_order; + return this->_channel_order; } void BasicChannel::setPreviousChannelId(ChannelId id) { @@ -153,95 +153,95 @@ BasicChannelTree::~BasicChannelTree() { } std::deque> BasicChannelTree::channels(const shared_ptr &root, int deep) { auto result = root ? this->entries_sub(root, deep) : this->entries(root, deep); - std::deque> res; + std::deque> res; for(const auto& entry : result) { - auto e = dynamic_pointer_cast(entry); - if(e) res.push_back(e); + auto e = dynamic_pointer_cast(entry); + if(e) res.push_back(e); } return res; } shared_ptr BasicChannelTree::findLinkedChannel(ts::ChannelId channelId) { - return this->find_linked_entry(channelId); + return this->find_linked_entry(channelId); } std::shared_ptr BasicChannelTree::findChannel(ChannelId channelId) { - if(channelId == 0) return nullptr; /* we start counting at 1! */ - return this->findChannel(channelId, this->channels()); + if(channelId == 0) return nullptr; /* we start counting at 1! */ + return this->findChannel(channelId, this->channels()); } std::shared_ptr BasicChannelTree::findChannel(ChannelId channelId, std::deque> avariable) { - for (auto elm : avariable) - if (elm->channelId() == channelId) - return elm; - return nullptr; + for (auto elm : avariable) + if (elm->channelId() == channelId) + return elm; + return nullptr; } std::shared_ptr BasicChannelTree::findChannel(const std::string &name, const shared_ptr &layer) { - for (auto elm : this->channels()) - if (elm->name() == name && elm->parent() == layer) - return elm; - return nullptr; + for (auto elm : this->channels()) + if (elm->name() == name && elm->parent() == layer) + return elm; + return nullptr; } std::shared_ptr BasicChannelTree::findChannelByPath(const std::string &path) { int maxChannelDeep = 255; //FIXME - std::deque entries; - size_t index = 0; - do { - auto found = path.find('/', index); - if (found == index) { - index++; - continue; - } else if (found < path.length() && path[found - 1] == '\\') { - index++; - continue; - } - entries.push_back(query::unescape(path.substr(index, found - index), false)); - index = found + 1; - } while (index != 0 && entries.size() <= maxChannelDeep); + std::deque entries; + size_t index = 0; + do { + auto found = path.find('/', index); + if (found == index) { + index++; + continue; + } else if (found < path.length() && path[found - 1] == '\\') { + index++; + continue; + } + entries.push_back(query::unescape(path.substr(index, found - index), false)); + index = found + 1; + } while (index != 0 && entries.size() <= maxChannelDeep); - debugMessage(LOG_GENERAL, "Parsed channel path \"{}\". Entries:", path); - std::shared_ptr current = nullptr; - for (const auto &name : entries) { - current = this->findChannel(name, current); - debugMessage(LOG_GENERAL, " - \"{}\" {}", name, (current ? "found" : "unknown")); - if (!current) break; - } - return current; + debugMessage(LOG_GENERAL, "Parsed channel path \"{}\". Entries:", path); + std::shared_ptr current = nullptr; + for (const auto &name : entries) { + current = this->findChannel(name, current); + debugMessage(LOG_GENERAL, " - \"{}\" {}", name, (current ? "found" : "unknown")); + if (!current) break; + } + return current; } std::shared_ptr BasicChannelTree::createChannel(ChannelId parentId, ChannelId orderId, const string &name) { - auto parent = this->findChannel(parentId); - if (!parent && parentId != 0) return nullptr; + auto parent = this->findChannel(parentId); + if (!parent && parentId != 0) return nullptr; auto order = this->findChannel(orderId); if (!order && orderId != 0) return nullptr; - if (this->findChannel(name, parent)) return nullptr; + if (this->findChannel(name, parent)) return nullptr; - auto channelId = generateChannelId(); - if (channelId < 1) { - logger::logger(0)->error("Cant generate channel id."); - return nullptr; - } + auto channelId = generateChannelId(); + if (channelId < 1) { + logger::logger(0)->error("Cant generate channel id."); + return nullptr; + } - auto channel = this->allocateChannel(parent, channelId); - channel->properties()[property::CHANNEL_NAME] = name; + auto channel = this->allocateChannel(parent, channelId); + channel->properties()[property::CHANNEL_NAME] = name; - if(!this->insert_entry(channel, parent, order)) return nullptr; - return channel; + if(!this->insert_entry(channel, parent, order)) return nullptr; + return channel; } deque> BasicChannelTree::delete_channel_root(const std::shared_ptr &root) { deque> result; /* for(const auto& channels : this->channels(root)) { - std::lock_guard lock(channels->deleteLock); - channels->deleted = true; + std::lock_guard lock(channels->deleteLock); + channels->deleted = true; } */ auto channels = this->delete_entry(root); @@ -257,17 +257,17 @@ deque> BasicChannelTree::delete_channel_root(c } bool BasicChannelTree::setDefaultChannel(const shared_ptr &ch) { - if (!ch) return false; - for (const auto &elm : this->channels()) - elm->properties()[property::CHANNEL_FLAG_DEFAULT] = false; - ch->properties()[property::CHANNEL_FLAG_DEFAULT] = true; - return true; + if (!ch) return false; + for (const auto &elm : this->channels()) + elm->properties()[property::CHANNEL_FLAG_DEFAULT] = false; + ch->properties()[property::CHANNEL_FLAG_DEFAULT] = true; + return true; } std::shared_ptr BasicChannelTree::getDefaultChannel() { - for (auto elm : this->channels()) - if (elm->properties()[property::CHANNEL_FLAG_DEFAULT].as()) return elm; - return nullptr; + for (auto elm : this->channels()) + if (elm->properties()[property::CHANNEL_FLAG_DEFAULT].as()) return elm; + return nullptr; } void BasicChannelTree::on_channel_entry_deleted(const shared_ptr &ptr) { @@ -275,17 +275,17 @@ void BasicChannelTree::on_channel_entry_deleted(const shared_ptr & } std::shared_ptr BasicChannelTree::allocateChannel(const shared_ptr &parent, ChannelId channelId) { - return std::make_shared(parent, channelId); + return std::make_shared(parent, channelId); } ChannelId BasicChannelTree::generateChannelId() { - ChannelId currentChannelId = 1; - while (this->findChannel(currentChannelId)) currentChannelId++; - return currentChannelId; + ChannelId currentChannelId = 1; + while (this->findChannel(currentChannelId)) currentChannelId++; + return currentChannelId; } void BasicChannelTree::printChannelTree(std::function fn) { - this->print_tree([&](const std::shared_ptr& t_entry, int deep) { + this->print_tree([&](const std::shared_ptr& t_entry, int deep) { auto entry = dynamic_pointer_cast(t_entry); assert(entry); diff --git a/src/BasicChannel.h b/src/BasicChannel.h index 299c8b6..8e7f4be 100644 --- a/src/BasicChannel.h +++ b/src/BasicChannel.h @@ -28,12 +28,12 @@ namespace ts { BasicChannelEntry* children{}; - ~BasicChannelEntry() { - this->current = nullptr; - } + ~BasicChannelEntry() { + this->current = nullptr; + } }; - class BasicChannel : public TreeEntry { + class BasicChannel : public TreeEntry { public: BasicChannel(ChannelId parentId, ChannelId channelId); BasicChannel(std::shared_ptr parent, ChannelId channelId); @@ -54,40 +54,40 @@ namespace ts { bool defaultChannel() { return (*this->_properties)[property::CHANNEL_FLAG_DEFAULT]; } int64_t emptySince(); - inline std::chrono::system_clock::time_point createdTimestamp() { - return std::chrono::system_clock::time_point() + std::chrono::milliseconds(this->properties()[property::CHANNEL_CREATED_AT].as()); - } + inline std::chrono::system_clock::time_point createdTimestamp() { + return std::chrono::system_clock::time_point() + std::chrono::milliseconds(this->properties()[property::CHANNEL_CREATED_AT].as()); + } - ts_always_inline bool permission_require_property_update(const permission::PermissionType& permission) { - return permission == permission::i_icon_id || permission == permission::i_client_needed_talk_power; - } - std::vector update_properties_from_permissions(); + ts_always_inline bool permission_require_property_update(const permission::PermissionType& permission) { + return permission == permission::i_icon_id || permission == permission::i_client_needed_talk_power; + } + std::vector update_properties_from_permissions(); - inline bool permission_granted(const permission::PermissionType& permission, const permission::v2::PermissionFlaggedValue& granted_value, bool require_granted_value) { - auto permission_manager = this->permissions(); /* copy the manager */ - assert(permission_manager); - const auto data = permission_manager->permission_value_flagged(permission); - return BasicChannel::permission_granted(data,granted_value, require_granted_value); - } + inline bool permission_granted(const permission::PermissionType& permission, const permission::v2::PermissionFlaggedValue& granted_value, bool require_granted_value) { + auto permission_manager = this->permissions(); /* copy the manager */ + assert(permission_manager); + const auto data = permission_manager->permission_value_flagged(permission); + return BasicChannel::permission_granted(data,granted_value, require_granted_value); + } - ts_always_inline - static bool permission_granted(const permission::v2::PermissionFlaggedValue& channel_permission_value, const permission::v2::PermissionFlaggedValue& granted_value, bool require_granted_value) { - if(!channel_permission_value.has_value || channel_permission_value.value == 0) { - return !require_granted_value || granted_value.has_value; - } - if(channel_permission_value.value == -1) { - return granted_value.value == -1; - } - return granted_value.value >= channel_permission_value.value; - } + ts_always_inline + static bool permission_granted(const permission::v2::PermissionFlaggedValue& channel_permission_value, const permission::v2::PermissionFlaggedValue& granted_value, bool require_granted_value) { + if(!channel_permission_value.has_value || channel_permission_value.value == 0) { + return !require_granted_value || granted_value.has_value; + } + if(channel_permission_value.value == -1) { + return granted_value.value == -1; + } + return granted_value.value >= channel_permission_value.value; + } - ts_always_inline bool talk_power_granted(const permission::v2::PermissionFlaggedValue& granted_value) { - return this->permission_granted(permission::i_client_needed_talk_power, granted_value, false); - } + ts_always_inline bool talk_power_granted(const permission::v2::PermissionFlaggedValue& granted_value) { + return this->permission_granted(permission::i_client_needed_talk_power, granted_value, false); + } - ts_always_inline std::shared_ptr permissions(){ return this->_permissions; } + ts_always_inline std::shared_ptr permissions(){ return this->_permissions; } virtual void setPermissionManager(const std::shared_ptr&); - virtual void setProperties(const std::shared_ptr&); + virtual void setProperties(const std::shared_ptr&); protected: public: ChannelId channelId() const override; @@ -95,13 +95,13 @@ namespace ts { void setPreviousChannelId(ChannelId id) override; void setParentChannelId(ChannelId id) override; void setLinkedHandle(const std::weak_ptr &) override; - protected: + protected: std::weak_ptr _link; std::shared_ptr _properties; std::shared_ptr _permissions; - ChannelId _channel_order = 0; - ChannelId _channel_id = 0; + ChannelId _channel_order = 0; + ChannelId _channel_id = 0; }; class BasicChannelTree : public TreeView { @@ -111,9 +111,9 @@ namespace ts { size_t channel_count() { return this->entry_count(); } - std::shared_ptr findLinkedChannel(ChannelId channelId); + std::shared_ptr findLinkedChannel(ChannelId channelId); std::shared_ptr findChannel(ChannelId channelId); - std::shared_ptr findChannel(ChannelId channelId, std::deque> avariable); + std::shared_ptr findChannel(ChannelId channelId, std::deque> avariable); std::shared_ptr findChannel(const std::string &name, const std::shared_ptr &layer); std::shared_ptr findChannelByPath(const std::string& path); //std::deque> topChannels(); diff --git a/src/Definitions.h b/src/Definitions.h index b0f8b5b..dfad052 100644 --- a/src/Definitions.h +++ b/src/Definitions.h @@ -19,7 +19,7 @@ namespace ts { typedef uint16_t FloodPoints; typedef uint64_t BanId; typedef uint32_t LetterId; - typedef uint32_t SongId; + typedef uint32_t SongId; typedef uint32_t IconId; typedef uint32_t PlaylistId; @@ -38,16 +38,16 @@ namespace ts { _LicenseType_MAX = LICENSE_AUTOMATIC_INSTANCE, }; /* - enum ServerLicenseType : uint8_t { - SERVER_LICENSE_NONE, - SERVER_LICENSE_OFFLINE, - SERVER_LICENSE_SDK, - SERVER_LICENSE_SDKOFFLINE, - SERVER_LICENSE_NPL, - SERVER_LICENSE_ATHP, - SERVER_LICENSE_AAL, - SERVER_LICENSE_DEFAULT, - }; + enum ServerLicenseType : uint8_t { + SERVER_LICENSE_NONE, + SERVER_LICENSE_OFFLINE, + SERVER_LICENSE_SDK, + SERVER_LICENSE_SDKOFFLINE, + SERVER_LICENSE_NPL, + SERVER_LICENSE_ATHP, + SERVER_LICENSE_AAL, + SERVER_LICENSE_DEFAULT, + }; */ enum PluginTargetMode : uint8_t { @@ -74,11 +74,11 @@ namespace ts { VREASON_SERVER_SHUTDOWN = 11 }; - struct ViewReasonSystemT { }; - static constexpr auto ViewReasonSystem = ViewReasonSystemT{}; + struct ViewReasonSystemT { }; + static constexpr auto ViewReasonSystem = ViewReasonSystemT{}; - struct ViewReasonServerLeftT { }; - static constexpr auto ViewReasonServerLeft = ViewReasonServerLeftT{}; + struct ViewReasonServerLeftT { }; + static constexpr auto ViewReasonServerLeft = ViewReasonServerLeftT{}; enum ChatMessageMode : uint8_t { TEXTMODE_PRIVATE = 1, @@ -149,7 +149,7 @@ namespace ts { QEVENTSPECIFIER_CHANNEL_DELETED = 5, QEVENTSPECIFIER_MUSIC_QUEUE = 0, - QEVENTSPECIFIER_MUSIC_PLAYER = 1, + QEVENTSPECIFIER_MUSIC_PLAYER = 1, QEVENTSPECIFIER_MAX = 6, }; @@ -157,8 +157,8 @@ namespace ts { #define DEFINE_TRANSFORMS(a, b) \ - DEFINE_CONVERTER_ENUM(a, b); \ - DEFINE_VARIABLE_TRANSFORM_ENUM(a, b); + DEFINE_CONVERTER_ENUM(a, b); \ + DEFINE_VARIABLE_TRANSFORM_ENUM(a, b); DEFINE_TRANSFORMS(ts::server::ConnectionState, uint8_t); DEFINE_TRANSFORMS(ts::server::ClientType, uint8_t); diff --git a/src/Error.h b/src/Error.h index 4fe90df..b177307 100644 --- a/src/Error.h +++ b/src/Error.h @@ -20,238 +20,238 @@ namespace ts { struct error { enum type : uint16_t { ok = 0x0, - undefined = 0x1, - not_implemented = 0x2, - lib_time_limit_reached = 0x5, - command_not_found = 0x100, - unable_to_bind_network_port = 0x101, - no_network_port_available = 0x102, - client_invalid_id = 0x200, - client_nickname_inuse = 0x201, - invalid_error_code = 0x202, - client_protocol_limit_reached = 0x203, - client_invalid_type = 0x204, - client_already_subscribed = 0x205, - client_not_logged_in = 0x206, - client_could_not_validate_identity = 0x207, - client_invalid_password = 0x208, - client_too_many_clones_connected = 0x209, - client_version_outdated = 0x20a, - client_is_online = 0x20b, - client_is_flooding = 0x20c, - client_hacked = 0x20d, - client_cannot_verify_now = 0x20e, - client_login_not_permitted = 0x20f, - client_not_subscribed = 0x210, - channel_invalid_id = 0x300, - channel_protocol_limit_reached = 0x301, - channel_already_in = 0x302, - channel_name_inuse = 0x303, - channel_not_empty = 0x304, - channel_can_not_delete_default = 0x305, - channel_default_require_permanent = 0x306, - channel_invalid_flags = 0x307, - channel_parent_not_permanent = 0x308, - channel_maxclients_reached = 0x309, - channel_maxfamily_reached = 0x30a, - channel_invalid_order = 0x30b, - channel_no_filetransfer_supported = 0x30c, - channel_invalid_password = 0x30d, - channel_is_private_channel = 0x30e, - channel_invalid_security_hash = 0x30f, - channel_is_deleted = 0x310, - server_invalid_id = 0x400, - server_running = 0x401, - server_is_shutting_down = 0x402, - server_maxclients_reached = 0x403, - server_invalid_password = 0x404, - server_deployment_active = 0x405, - server_unable_to_stop_own_server = 0x406, - server_is_virtual = 0x407, - server_wrong_machineid = 0x408, - server_is_not_running = 0x409, - server_is_booting = 0x40a, - server_status_invalid = 0x40b, - server_modal_quit = 0x40c, - server_version_outdated = 0x40d, - server_already_joined = 0x40d, - server_is_not_shutting_down = 0x40e, - sql = 0x500, - database_empty_result = 0x501, - database_duplicate_entry = 0x502, - database_no_modifications = 0x503, - database_constraint = 0x504, - database_reinvoke = 0x505, - parameter_quote = 0x600, - parameter_invalid_count = 0x601, - parameter_invalid = 0x602, - parameter_not_found = 0x603, - parameter_convert = 0x604, - parameter_invalid_size = 0x605, - parameter_missing = 0x606, - parameter_checksum = 0x607, - vs_critical = 0x700, - connection_lost = 0x701, - not_connected = 0x702, - no_cached_connection_info = 0x703, - currently_not_possible = 0x704, - failed_connection_initialisation = 0x705, - could_not_resolve_hostname = 0x706, - invalid_server_connection_handler_id = 0x707, - could_not_initialise_input_client = 0x708, - clientlibrary_not_initialised = 0x709, - serverlibrary_not_initialised = 0x70a, - whisper_too_many_targets = 0x70b, - whisper_no_targets = 0x70c, - file_invalid_name = 0x800, - file_invalid_permissions = 0x801, - file_already_exists = 0x802, - file_not_found = 0x803, - file_io_error = 0x804, - file_invalid_transfer_id = 0x805, - file_invalid_path = 0x806, - file_no_files_available = 0x807, - file_overwrite_excludes_resume = 0x808, - file_invalid_size = 0x809, - file_already_in_use = 0x80a, - file_could_not_open_connection = 0x80b, - file_no_space_left_on_device = 0x80c, - file_exceeds_file_system_maximum_size = 0x80d, - file_transfer_connection_timeout = 0x80e, - file_connection_lost = 0x80f, - file_exceeds_supplied_size = 0x810, - file_transfer_complete = 0x811, - file_transfer_canceled = 0x812, - file_transfer_interrupted = 0x813, - file_transfer_server_quota_exceeded = 0x814, - file_transfer_client_quota_exceeded = 0x815, - file_transfer_reset = 0x816, - file_transfer_limit_reached = 0x817, - server_insufficeient_permissions = 0xa08, - accounting_slot_limit_reached = 0xb01, - server_connect_banned = 0xd01, - ban_flooding = 0xd03, - token_invalid_id = 0xf00, - web_handshake_invalid = 0x1001, - web_handshake_unsupported = 0x1001, - web_handshake_identity_unsupported = 0x1002, - web_handshake_identity_proof_failed = 0x1002, - music_invalid_id = 0x1100, - music_limit_reached = 0x1101, - music_client_limit_reached = 0x1102, - music_invalid_player_state = 0x1103, - music_invalid_action = 0x1104, - music_no_player = 0x1105, - music_disabled = 0x1105, - playlist_invalid_id = 0x2100, - playlist_invalid_song_id = 0x2101, - playlist_already_in_use = 0x2102, - playlist_is_in_use = 0x2103, - query_not_exists = 0x1200, - query_already_exists = 0x1201, - custom_error = 0xffff + undefined = 0x1, + not_implemented = 0x2, + lib_time_limit_reached = 0x5, + command_not_found = 0x100, + unable_to_bind_network_port = 0x101, + no_network_port_available = 0x102, + client_invalid_id = 0x200, + client_nickname_inuse = 0x201, + invalid_error_code = 0x202, + client_protocol_limit_reached = 0x203, + client_invalid_type = 0x204, + client_already_subscribed = 0x205, + client_not_logged_in = 0x206, + client_could_not_validate_identity = 0x207, + client_invalid_password = 0x208, + client_too_many_clones_connected = 0x209, + client_version_outdated = 0x20a, + client_is_online = 0x20b, + client_is_flooding = 0x20c, + client_hacked = 0x20d, + client_cannot_verify_now = 0x20e, + client_login_not_permitted = 0x20f, + client_not_subscribed = 0x210, + channel_invalid_id = 0x300, + channel_protocol_limit_reached = 0x301, + channel_already_in = 0x302, + channel_name_inuse = 0x303, + channel_not_empty = 0x304, + channel_can_not_delete_default = 0x305, + channel_default_require_permanent = 0x306, + channel_invalid_flags = 0x307, + channel_parent_not_permanent = 0x308, + channel_maxclients_reached = 0x309, + channel_maxfamily_reached = 0x30a, + channel_invalid_order = 0x30b, + channel_no_filetransfer_supported = 0x30c, + channel_invalid_password = 0x30d, + channel_is_private_channel = 0x30e, + channel_invalid_security_hash = 0x30f, + channel_is_deleted = 0x310, + server_invalid_id = 0x400, + server_running = 0x401, + server_is_shutting_down = 0x402, + server_maxclients_reached = 0x403, + server_invalid_password = 0x404, + server_deployment_active = 0x405, + server_unable_to_stop_own_server = 0x406, + server_is_virtual = 0x407, + server_wrong_machineid = 0x408, + server_is_not_running = 0x409, + server_is_booting = 0x40a, + server_status_invalid = 0x40b, + server_modal_quit = 0x40c, + server_version_outdated = 0x40d, + server_already_joined = 0x40d, + server_is_not_shutting_down = 0x40e, + sql = 0x500, + database_empty_result = 0x501, + database_duplicate_entry = 0x502, + database_no_modifications = 0x503, + database_constraint = 0x504, + database_reinvoke = 0x505, + parameter_quote = 0x600, + parameter_invalid_count = 0x601, + parameter_invalid = 0x602, + parameter_not_found = 0x603, + parameter_convert = 0x604, + parameter_invalid_size = 0x605, + parameter_missing = 0x606, + parameter_checksum = 0x607, + vs_critical = 0x700, + connection_lost = 0x701, + not_connected = 0x702, + no_cached_connection_info = 0x703, + currently_not_possible = 0x704, + failed_connection_initialisation = 0x705, + could_not_resolve_hostname = 0x706, + invalid_server_connection_handler_id = 0x707, + could_not_initialise_input_client = 0x708, + clientlibrary_not_initialised = 0x709, + serverlibrary_not_initialised = 0x70a, + whisper_too_many_targets = 0x70b, + whisper_no_targets = 0x70c, + file_invalid_name = 0x800, + file_invalid_permissions = 0x801, + file_already_exists = 0x802, + file_not_found = 0x803, + file_io_error = 0x804, + file_invalid_transfer_id = 0x805, + file_invalid_path = 0x806, + file_no_files_available = 0x807, + file_overwrite_excludes_resume = 0x808, + file_invalid_size = 0x809, + file_already_in_use = 0x80a, + file_could_not_open_connection = 0x80b, + file_no_space_left_on_device = 0x80c, + file_exceeds_file_system_maximum_size = 0x80d, + file_transfer_connection_timeout = 0x80e, + file_connection_lost = 0x80f, + file_exceeds_supplied_size = 0x810, + file_transfer_complete = 0x811, + file_transfer_canceled = 0x812, + file_transfer_interrupted = 0x813, + file_transfer_server_quota_exceeded = 0x814, + file_transfer_client_quota_exceeded = 0x815, + file_transfer_reset = 0x816, + file_transfer_limit_reached = 0x817, + server_insufficeient_permissions = 0xa08, + accounting_slot_limit_reached = 0xb01, + server_connect_banned = 0xd01, + ban_flooding = 0xd03, + token_invalid_id = 0xf00, + web_handshake_invalid = 0x1001, + web_handshake_unsupported = 0x1001, + web_handshake_identity_unsupported = 0x1002, + web_handshake_identity_proof_failed = 0x1002, + music_invalid_id = 0x1100, + music_limit_reached = 0x1101, + music_client_limit_reached = 0x1102, + music_invalid_player_state = 0x1103, + music_invalid_action = 0x1104, + music_no_player = 0x1105, + music_disabled = 0x1105, + playlist_invalid_id = 0x2100, + playlist_invalid_song_id = 0x2101, + playlist_already_in_use = 0x2102, + playlist_is_in_use = 0x2103, + query_not_exists = 0x1200, + query_already_exists = 0x1201, + custom_error = 0xffff }; }; - struct detailed_command_result { - error::type error_id; - std::map extra_properties; - }; + struct detailed_command_result { + error::type error_id; + std::map extra_properties; + }; - /* - * return command_result{permission::b_virtualserver_select_godmode}; => movabs rax,0xa08001700000001; ret; (Only if there is no deconstructor!) - * return command_result{permission::b_virtualserver_select_godmode}; => movabs rax,0xa08001700000001; ret; (Only if there is no deconstructor!) - * return command_result{error::vs_critical, "unknown error"}; => To a lot of code - */ + /* + * return command_result{permission::b_virtualserver_select_godmode}; => movabs rax,0xa08001700000001; ret; (Only if there is no deconstructor!) + * return command_result{permission::b_virtualserver_select_godmode}; => movabs rax,0xa08001700000001; ret; (Only if there is no deconstructor!) + * return command_result{error::vs_critical, "unknown error"}; => To a lot of code + */ 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_PERMISSION = ~((uint64_t) 1 << (sizeof(permission::PermissionType) * 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 uint8_t OFFSET_ERROR = (8 - 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. - * 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) - * - * 1 means code - * 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] - */ - uint64_t data = 0; + 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; + /* + * 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)) + * bits [0;64] => data ptr (needs to be zero at destruction to avoid memory leaks) + * + * 1 means code + * 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] + */ + uint64_t data = 0; - /* Test for mode 1 as described before */ - static_assert(sizeof(permission::PermissionType) * 8 + sizeof(error::type) * 8 <= 63); + /* Test for mode 1 as described before */ + static_assert(sizeof(permission::PermissionType) * 8 + sizeof(error::type) * 8 <= 63); - inline error::type error_code() { - return (error::type) ((this->data >> OFFSET_ERROR) & MASK_ERROR); - } + inline error::type error_code() { + return (error::type) ((this->data >> OFFSET_ERROR) & MASK_ERROR); + } - inline error::type permission_id() { - return (error::type) ((this->data >> OFFSET_PERMISSION) & MASK_PERMISSION); - } + inline error::type permission_id() { + return (error::type) ((this->data >> OFFSET_PERMISSION) & MASK_PERMISSION); + } - inline detailed_command_result* details() { - return (detailed_command_result*) this->data; - } + inline detailed_command_result* details() { + return (detailed_command_result*) this->data; + } - inline bool is_detailed() { - return (this->data & 0x1UL) == 0; - } + inline bool is_detailed() { + return (this->data & 0x1UL) == 0; + } - inline detailed_command_result* release_details() { - auto result = this->details(); - this->data = 0; - return result; - } + inline detailed_command_result* release_details() { + auto result = this->details(); + this->data = 0; + return 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 */ - command_result(command_result&) = delete; - command_result(const command_result&) = delete; - command_result(command_result&& other) : data(other.data) { - other.data = 0; - } + command_result(command_result&) = delete; + command_result(const command_result&) = delete; + command_result(command_result&& other) : data(other.data) { + other.data = 0; + } #endif - command_result() = default; + command_result() = default; - explicit command_result(permission::PermissionType permission) { - this->data = 0x01; /* the the type to 1 */ + explicit command_result(permission::PermissionType permission) { + this->data = 0x01; /* the the type to 1 */ - this->data |= (uint64_t) error::server_insufficeient_permissions << OFFSET_ERROR; - this->data |= (uint64_t) permission << OFFSET_PERMISSION; - } + this->data |= (uint64_t) error::server_insufficeient_permissions << OFFSET_ERROR; + this->data |= (uint64_t) permission << OFFSET_PERMISSION; + } - explicit command_result(error::type error) { - this->data = 0x01; /* the the type to 1 */ + explicit command_result(error::type error) { + 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) { - auto details_ptr = new detailed_command_result{}; - assert(((uintptr_t) details_ptr & 0x01) == 0); // must be aligned! + command_result(error::type error, const std::string& message) { + auto details_ptr = new detailed_command_result{}; + assert(((uintptr_t) details_ptr & 0x01) == 0); // must be aligned! - this->data = (uintptr_t) details_ptr; + this->data = (uintptr_t) details_ptr; - details_ptr->error_id = error; - details_ptr->extra_properties["extra_msg"] = message; - } + details_ptr->error_id = error; + details_ptr->extra_properties["extra_msg"] = message; + } - command_result(error::type error, const std::map& properties) : command_result{error, ""} { - assert(this->is_detailed()); - this->details()->extra_properties = properties; - } + command_result(error::type error, const std::map& properties) : command_result{error, ""} { + assert(this->is_detailed()); + this->details()->extra_properties = properties; + } #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 */ - ~command_result() { - if((this->data & 0x01) == 0x00) { - // this->details needs to be removed 'till this gets destructed - assert(this->data == 0); - } - } + /* 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() { + if((this->data & 0x01) == 0x00) { + // this->details needs to be removed 'till this gets destructed + assert(this->data == 0); + } + } #endif }; static_assert(sizeof(command_result) == 8); diff --git a/src/EventLoop.cpp b/src/EventLoop.cpp index 2b588f0..46343b7 100644 --- a/src/EventLoop.cpp +++ b/src/EventLoop.cpp @@ -12,213 +12,213 @@ using namespace ts::event; EventExecutor::EventExecutor(const std::string& thread_prefix) : _thread_prefix(thread_prefix) {} EventExecutor::~EventExecutor() { - unique_lock lock(this->lock); - this->_shutdown(lock); - this->_reset_events(lock); + unique_lock lock(this->lock); + this->_shutdown(lock); + this->_reset_events(lock); } void EventExecutor::threads(int threads) { - unique_lock lock(this->lock); + unique_lock lock(this->lock); - if(this->target_threads == threads) - return; + if(this->target_threads == threads) + return; - this->target_threads = threads; - while(this->_threads.size() < threads) - this->_spawn_executor(lock); + this->target_threads = threads; + while(this->_threads.size() < threads) + this->_spawn_executor(lock); - if(this->_threads.size() > threads) { - this->should_adjust = true; - this->condition.notify_all(); - } + if(this->_threads.size() > threads) { + this->should_adjust = true; + this->condition.notify_all(); + } #ifndef WIN32 - this->_reassign_thread_names(lock); + this->_reassign_thread_names(lock); #endif } bool EventExecutor::initialize(int threads) { - unique_lock lock(this->lock); - this->_shutdown(lock); - if(!lock.owns_lock()) - lock.lock(); + unique_lock lock(this->lock); + this->_shutdown(lock); + if(!lock.owns_lock()) + lock.lock(); - this->should_shutdown = false; - while(threads-- > 0) - _spawn_executor(lock); + this->should_shutdown = false; + while(threads-- > 0) + _spawn_executor(lock); #ifndef WIN32 - this->_reassign_thread_names(lock); + this->_reassign_thread_names(lock); #endif - return true; + return true; } void EventExecutor::_spawn_executor(std::unique_lock& lock) { - if(!lock.owns_lock()) - lock.lock(); + if(!lock.owns_lock()) + lock.lock(); - this->_threads.emplace_back(&EventExecutor::_executor, this); + this->_threads.emplace_back(&EventExecutor::_executor, this); } void EventExecutor::shutdown() { - unique_lock lock(this->lock); - this->_shutdown(lock); + unique_lock lock(this->lock); + this->_shutdown(lock); } bool EventExecutor::schedule(const std::shared_ptr &entry) { - unique_lock lock(this->lock); - if(!entry || entry->_event_ptr) - return true; /* already scheduled */ + unique_lock lock(this->lock); + if(!entry || entry->_event_ptr) + return true; /* already scheduled */ - auto linked_entry = new LinkedEntry{}; - linked_entry->entry = entry; - linked_entry->next = nullptr; - linked_entry->previous = this->tail; - linked_entry->scheduled = std::chrono::system_clock::now(); + auto linked_entry = new LinkedEntry{}; + linked_entry->entry = entry; + linked_entry->next = nullptr; + linked_entry->previous = this->tail; + linked_entry->scheduled = std::chrono::system_clock::now(); - if(this->tail) { - this->tail->next = linked_entry; - this->tail = linked_entry; - } else { - this->head = linked_entry; - this->tail = linked_entry; - } - this->condition.notify_one(); + if(this->tail) { + this->tail->next = linked_entry; + this->tail = linked_entry; + } else { + this->head = linked_entry; + this->tail = linked_entry; + } + this->condition.notify_one(); - entry->_event_ptr = linked_entry; - return true; + entry->_event_ptr = linked_entry; + return true; } bool EventExecutor::cancel(const std::shared_ptr &entry) { - unique_lock lock(this->lock); - if(!entry || !entry->_event_ptr) - return false; + unique_lock lock(this->lock); + if(!entry || !entry->_event_ptr) + return false; - auto linked_entry = (LinkedEntry*) entry->_event_ptr; - entry->_event_ptr = nullptr; + auto linked_entry = (LinkedEntry*) entry->_event_ptr; + entry->_event_ptr = nullptr; - this->head = linked_entry->next; - if(this->head) { - assert(linked_entry == this->head->previous); - this->head->previous = nullptr; - } else { - assert(linked_entry == this->tail); - this->tail = nullptr; - } + this->head = linked_entry->next; + if(this->head) { + assert(linked_entry == this->head->previous); + this->head->previous = nullptr; + } else { + assert(linked_entry == this->tail); + this->tail = nullptr; + } - delete linked_entry; - return true; + delete linked_entry; + return true; } void EventExecutor::_shutdown(std::unique_lock &lock) { - if(!lock.owns_lock()) - lock.lock(); + if(!lock.owns_lock()) + lock.lock(); - this->should_shutdown = true; - this->condition.notify_all(); - lock.unlock(); - for(auto& thread : this->_threads) - if(thread.joinable()) { - try { - thread.join(); /* TODO: Timeout? */ - } catch(std::system_error& ex) { - if(ex.code() != errc::invalid_argument) /* thread is not joinable anymore :) */ - throw; - } - } - lock.lock(); - this->should_shutdown = false; + this->should_shutdown = true; + this->condition.notify_all(); + lock.unlock(); + for(auto& thread : this->_threads) + if(thread.joinable()) { + try { + thread.join(); /* TODO: Timeout? */ + } catch(std::system_error& ex) { + if(ex.code() != errc::invalid_argument) /* thread is not joinable anymore :) */ + throw; + } + } + lock.lock(); + this->should_shutdown = false; } void EventExecutor::_reset_events(std::unique_lock &lock) { - if(!lock.owns_lock()) - lock.lock(); + if(!lock.owns_lock()) + lock.lock(); - auto entry = this->head; - while(entry) { - auto next = entry->next; - delete entry; - entry = next; - } - this->head = nullptr; - this->tail = nullptr; + auto entry = this->head; + while(entry) { + auto next = entry->next; + delete entry; + entry = next; + } + this->head = nullptr; + this->tail = nullptr; } #ifndef WIN32 void EventExecutor::_reassign_thread_names(std::unique_lock &lock) { - if(!lock.owns_lock()) - lock.lock(); + if(!lock.owns_lock()) + lock.lock(); - size_t index = 1; - for(auto& thread : this->_threads) { - auto handle = thread.native_handle(); - auto name = this->_thread_prefix + to_string(index++); - pthread_setname_np(handle, name.c_str()); - } + size_t index = 1; + for(auto& thread : this->_threads) { + auto handle = thread.native_handle(); + auto name = this->_thread_prefix + to_string(index++); + pthread_setname_np(handle, name.c_str()); + } } #endif void EventExecutor::_executor(ts::event::EventExecutor *loop) { - while(true) { - sassert(std::addressof(loop->lock) != nullptr); + while(true) { + sassert(std::addressof(loop->lock) != nullptr); - unique_lock lock(loop->lock); - loop->condition.wait(lock, [&] { - return loop->should_shutdown || loop->should_adjust || loop->head != nullptr; - }); - if(loop->should_shutdown) - break; + unique_lock lock(loop->lock); + loop->condition.wait(lock, [&] { + return loop->should_shutdown || loop->should_adjust || loop->head != nullptr; + }); + if(loop->should_shutdown) + break; - if(loop->should_adjust) { - const auto current_threads = loop->_threads.size(); - if(current_threads > loop->target_threads) { - /* terminate this loop */ + if(loop->should_adjust) { + const auto current_threads = loop->_threads.size(); + if(current_threads > loop->target_threads) { + /* terminate this loop */ - auto thread_id = std::this_thread::get_id(); - auto index = std::find_if(loop->_threads.begin(), loop->_threads.end(), [&](const std::thread& thread) { return thread_id == thread.get_id(); }); - if(index == loop->_threads.end()) { - /* TODO: Log error */ - } else { - (*index).detach(); /* lets detach ourselfs before we delete the handle */ - loop->_threads.erase(index); - } - loop->should_adjust = ((current_threads - 1) != loop->target_threads); - return; /* we're out now! */ - } else { - loop->should_adjust = false; - } + auto thread_id = std::this_thread::get_id(); + auto index = std::find_if(loop->_threads.begin(), loop->_threads.end(), [&](const std::thread& thread) { return thread_id == thread.get_id(); }); + if(index == loop->_threads.end()) { + /* TODO: Log error */ + } else { + (*index).detach(); /* lets detach ourselfs before we delete the handle */ + loop->_threads.erase(index); + } + loop->should_adjust = ((current_threads - 1) != loop->target_threads); + return; /* we're out now! */ + } else { + loop->should_adjust = false; + } #ifndef WIN32 - if(!loop->should_adjust) - loop->_reassign_thread_names(lock); + if(!loop->should_adjust) + loop->_reassign_thread_names(lock); #endif - } + } - if(!loop->head) - continue; + if(!loop->head) + continue; - auto linked_entry = loop->head; - loop->head = linked_entry->next; - if(loop->head) { - sassert(linked_entry == loop->head->previous); - loop->head->previous = nullptr; - } else { - sassert(linked_entry == loop->tail); - loop->tail = nullptr; - } + auto linked_entry = loop->head; + loop->head = linked_entry->next; + if(loop->head) { + sassert(linked_entry == loop->head->previous); + loop->head->previous = nullptr; + } else { + sassert(linked_entry == loop->tail); + loop->tail = nullptr; + } - auto event_handler = linked_entry->entry.lock(); - if(!event_handler) { - /* event handler passed away while waiting for beeing executed */ - delete linked_entry; - continue; - } + auto event_handler = linked_entry->entry.lock(); + if(!event_handler) { + /* event handler passed away while waiting for beeing executed */ + delete linked_entry; + continue; + } - sassert(event_handler->_event_ptr == linked_entry); - event_handler->_event_ptr = nullptr; - lock.unlock(); + sassert(event_handler->_event_ptr == linked_entry); + event_handler->_event_ptr = nullptr; + lock.unlock(); - event_handler->event_execute(linked_entry->scheduled); - delete linked_entry; - } + event_handler->event_execute(linked_entry->scheduled); + delete linked_entry; + } } \ No newline at end of file diff --git a/src/EventLoop.h b/src/EventLoop.h index 8b5c717..b0a7a54 100644 --- a/src/EventLoop.h +++ b/src/EventLoop.h @@ -8,81 +8,81 @@ #include namespace ts { - namespace event { - class EventExecutor; + namespace event { + class EventExecutor; - class EventEntry { - friend class EventExecutor; - public: - virtual void event_execute(const std::chrono::system_clock::time_point& /* scheduled timestamp */) = 0; + class EventEntry { + friend class EventExecutor; + public: + virtual void event_execute(const std::chrono::system_clock::time_point& /* scheduled timestamp */) = 0; - private: - void* _event_ptr = nullptr; - }; + private: + void* _event_ptr = nullptr; + }; - template - class ProxiedEventEntry : public event::EventEntry { - public: - using callback_t = void(class_t::*)(const std::chrono::system_clock::time_point &); + template + class ProxiedEventEntry : public event::EventEntry { + public: + using callback_t = void(class_t::*)(const std::chrono::system_clock::time_point &); - ProxiedEventEntry(const std::shared_ptr& _instance, callback_t callback) : instance(_instance), callback(callback) { } + ProxiedEventEntry(const std::shared_ptr& _instance, callback_t callback) : instance(_instance), callback(callback) { } - std::weak_ptr instance; - callback_t callback; + std::weak_ptr instance; + callback_t callback; - void event_execute(const std::chrono::system_clock::time_point &point) override { - auto _instance = this->instance.lock(); - if(!_instance) - return; + void event_execute(const std::chrono::system_clock::time_point &point) override { + auto _instance = this->instance.lock(); + if(!_instance) + return; - ((void(*)(class_t*, const std::chrono::system_clock::time_point &)) (void*) this->callback)(&*_instance, point); - } - }; + ((void(*)(class_t*, const std::chrono::system_clock::time_point &)) (void*) this->callback)(&*_instance, point); + } + }; - class EventExecutor { - public: - explicit EventExecutor(const std::string& /* thread prefix */); - virtual ~EventExecutor(); + class EventExecutor { + public: + explicit EventExecutor(const std::string& /* thread prefix */); + virtual ~EventExecutor(); - bool initialize(int /* num threads */); - bool schedule(const std::shared_ptr& /* entry */); - bool cancel(const std::shared_ptr& /* entry */); /* Note: Will not cancel already running executes */ - void shutdown(); + bool initialize(int /* num threads */); + bool schedule(const std::shared_ptr& /* entry */); + bool cancel(const std::shared_ptr& /* entry */); /* Note: Will not cancel already running executes */ + 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 */); - inline int threads() const { return this->target_threads; } - private: - struct LinkedEntry { - LinkedEntry* previous; - LinkedEntry* next; + void threads(int /* num threads */); + inline int threads() const { return this->target_threads; } + private: + struct LinkedEntry { + LinkedEntry* previous; + LinkedEntry* next; - std::chrono::system_clock::time_point scheduled; - std::weak_ptr entry; - }; + std::chrono::system_clock::time_point scheduled; + std::weak_ptr entry; + }; - static void _executor(EventExecutor*); - void _spawn_executor(std::unique_lock&); - void _shutdown(std::unique_lock&); - void _reset_events(std::unique_lock&); + static void _executor(EventExecutor*); + void _spawn_executor(std::unique_lock&); + void _shutdown(std::unique_lock&); + void _reset_events(std::unique_lock&); #ifndef WIN32 - void _reassign_thread_names(std::unique_lock&); + void _reassign_thread_names(std::unique_lock&); #endif - bool should_shutdown = true; - bool should_adjust = false; /* thread adjustments */ - int target_threads = 0; + bool should_shutdown = true; + bool should_adjust = false; /* thread adjustments */ + int target_threads = 0; - std::vector _threads; - std::mutex lock; - std::condition_variable condition; + std::vector _threads; + std::mutex lock; + std::condition_variable condition; - LinkedEntry* head = nullptr; - LinkedEntry* tail = nullptr; + LinkedEntry* head = nullptr; + LinkedEntry* tail = nullptr; - std::string _thread_prefix; - }; - } + std::string _thread_prefix; + }; + } } \ No newline at end of file diff --git a/src/License.cpp b/src/License.cpp index b585f2c..0186b34 100644 --- a/src/License.cpp +++ b/src/License.cpp @@ -16,10 +16,10 @@ using namespace std; using namespace std::chrono; LicensePublicKey license::teamspeak::public_root = - {0xcd, 0x0d, 0xe2, 0xae, 0xd4, 0x63, 0x45, 0x50, - 0x9a, 0x7e, 0x3c, 0xfd, 0x8f, 0x68, 0xb3, 0xdc, - 0x75, 0x55, 0xb2, 0x9d, 0xcc, 0xec, 0x73, 0xcd, - 0x18, 0x75, 0x0f, 0x99, 0x38, 0x12, 0x40, 0x8a}; + {0xcd, 0x0d, 0xe2, 0xae, 0xd4, 0x63, 0x45, 0x50, + 0x9a, 0x7e, 0x3c, 0xfd, 0x8f, 0x68, 0xb3, 0xdc, + 0x75, 0x55, 0xb2, 0x9d, 0xcc, 0xec, 0x73, 0xcd, + 0x18, 0x75, 0x0f, 0x99, 0x38, 0x12, 0x40, 0x8a}; //0DCB3688FFD3C7E9A504563D4AEE20DCD //8A401238990F7518CD73ECCC9DB25575 /* @@ -28,179 +28,179 @@ Public key: 0x41, 0x47, 0xeb, 0x8b, 0xab, 0xaa, 0x89, 0xb9, 0x34, 0x86, 0x76, 0x Private key: 0xa8, 0xcf, 0x96, 0xe8, 0xa8, 0xce, 0x33, 0x3b, 0x80, 0xb5, 0xd4, 0x27, 0x25, 0x62, 0xa6, 0x3a, 0x4a, 0x9e, 0x81, 0xf3, 0x05, 0xda, 0xb5, 0xf7, 0xe9, 0x35, 0x3d, 0x02, 0x81, 0x39, 0x8d, 0x64, */ LicensePublicKey license::teamspeak::public_tea_root = { - 0x41, 0x47, 0xeb, 0x8b, 0xab, 0xaa, 0x89, 0xb9, - 0x34, 0x86, 0x76, 0x25, 0x5f, 0x9b, 0xaf, 0x10, - 0xfb, 0x2b, 0x03, 0x62, 0x10, 0xd0, 0x18, 0x59, - 0x04, 0x42, 0x39, 0x5b, 0x2c, 0x22, 0xc3, 0x6a, + 0x41, 0x47, 0xeb, 0x8b, 0xab, 0xaa, 0x89, 0xb9, + 0x34, 0x86, 0x76, 0x25, 0x5f, 0x9b, 0xaf, 0x10, + 0xfb, 0x2b, 0x03, 0x62, 0x10, 0xd0, 0x18, 0x59, + 0x04, 0x42, 0x39, 0x5b, 0x2c, 0x22, 0xc3, 0x6a, }; LicensePublicKey license::teamspeak::private_tea_root = { - 0xa8, 0xcf, 0x96, 0xe8, 0xa8, 0xce, 0x33, 0x3b, 0x80, 0xb5, 0xd4, 0x27, 0x25, 0x62, 0xa6, 0x3a, 0x4a, 0x9e, 0x81, 0xf3, 0x05, 0xda, 0xb5, 0xf7, 0xe9, 0x35, 0x3d, 0x02, 0x81, 0x39, 0x8d, 0x64, + 0xa8, 0xcf, 0x96, 0xe8, 0xa8, 0xce, 0x33, 0x3b, 0x80, 0xb5, 0xd4, 0x27, 0x25, 0x62, 0xa6, 0x3a, 0x4a, 0x9e, 0x81, 0xf3, 0x05, 0xda, 0xb5, 0xf7, 0xe9, 0x35, 0x3d, 0x02, 0x81, 0x39, 0x8d, 0x64, }; /* //Could be found at linux x64 3.1.3 (1621edab12fd2cfc74aee73258fec2f1435e70f2): 0x9BDFE0 LicensePublicKey license::teamspeak::Anonymous::root_key = { - 0xA0, 0x23, 0xE6, 0x30, 0x0B, 0xDF, 0x91, 0x2E, 0xB3, 0xFD, 0x45, 0xA0, 0x86, 0x97, 0x1F, 0x97, - 0xE6, 0xBB, 0x10, 0xED, 0x75, 0x14, 0xC1, 0xA1, 0xFC, 0x31, 0x8A, 0x49, 0x58, 0x09, 0xDF, 0x78 + 0xA0, 0x23, 0xE6, 0x30, 0x0B, 0xDF, 0x91, 0x2E, 0xB3, 0xFD, 0x45, 0xA0, 0x86, 0x97, 0x1F, 0x97, + 0xE6, 0xBB, 0x10, 0xED, 0x75, 0x14, 0xC1, 0xA1, 0xFC, 0x31, 0x8A, 0x49, 0x58, 0x09, 0xDF, 0x78 }; size_t license::teamspeak::Anonymous::root_index = 1; //01 00 35 85 41 49 8A 24 AC D3 //Could be found at linux x64 3.1.3 (1621edab12fd2cfc74aee73258fec2f1435e70f2): 0x9BDFA0 uint8_t default_chain[] = { - 0x01, 0x00, 0x35, 0x85, 0x41, 0x49, 0x8A, 0x24, 0xAC, 0xD3, 0x01, 0x57, 0x91, 0x8B, 0x8F, 0x50, - 0x95, 0x5C, 0x0D, 0xAE, 0x97, 0x0A, 0xB6, 0x53, 0x72, 0xCB, 0xE4, 0x07, 0x41, 0x5F, 0xCF, 0x3E, - 0x02, 0x9B, 0x02, 0x08, 0x4D, 0x15, 0xE0, 0x0A, 0xA7, 0x93, 0x60, 0x07, 0x00, 0x00, 0x00, 0x20, - 0x41, 0x6E, 0x6F, 0x6E, 0x79, 0x6D, 0x6F, 0x75, 0x73 + 0x01, 0x00, 0x35, 0x85, 0x41, 0x49, 0x8A, 0x24, 0xAC, 0xD3, 0x01, 0x57, 0x91, 0x8B, 0x8F, 0x50, + 0x95, 0x5C, 0x0D, 0xAE, 0x97, 0x0A, 0xB6, 0x53, 0x72, 0xCB, 0xE4, 0x07, 0x41, 0x5F, 0xCF, 0x3E, + 0x02, 0x9B, 0x02, 0x08, 0x4D, 0x15, 0xE0, 0x0A, 0xA7, 0x93, 0x60, 0x07, 0x00, 0x00, 0x00, 0x20, + 0x41, 0x6E, 0x6F, 0x6E, 0x79, 0x6D, 0x6F, 0x75, 0x73 }; */ //9ED960 linux x64 uint8_t default_chain[] = { - 0x01, 0x00, 0x95, 0x5D, 0x39, 0x4A, 0x17, 0xE5, 0x10, 0x73, 0x4C, 0xA0, 0x6B, 0xDF, 0x5D, 0x39, - 0x0F, 0x45, 0x24, 0x2C, 0x0B, 0x68, 0x9A, 0xAD, 0x0D, 0xBD, 0x46, 0xEF, 0x16, 0x0F, 0x32, 0xF1, - 0xC5, 0x33, 0x02, 0x0A, 0x55, 0xF2, 0x80, 0x0C, 0x5E, 0xB3, 0x00, 0x07, 0x00, 0x00, 0x00, 0x20, - 0x41, 0x6E, 0x6F, 0x6E, 0x79, 0x6D, 0x6F, 0x75, 0x73 + 0x01, 0x00, 0x95, 0x5D, 0x39, 0x4A, 0x17, 0xE5, 0x10, 0x73, 0x4C, 0xA0, 0x6B, 0xDF, 0x5D, 0x39, + 0x0F, 0x45, 0x24, 0x2C, 0x0B, 0x68, 0x9A, 0xAD, 0x0D, 0xBD, 0x46, 0xEF, 0x16, 0x0F, 0x32, 0xF1, + 0xC5, 0x33, 0x02, 0x0A, 0x55, 0xF2, 0x80, 0x0C, 0x5E, 0xB3, 0x00, 0x07, 0x00, 0x00, 0x00, 0x20, + 0x41, 0x6E, 0x6F, 0x6E, 0x79, 0x6D, 0x6F, 0x75, 0x73 }; //9ED960 + sizeof(default_chain) + pad(16) LicensePublicKey license::teamspeak::Anonymous::root_key = { - 0x40, 0x25, 0x08, 0x56, 0xD8, 0xDA, 0x90, 0x85, 0x9E, 0xDC, 0x1A, 0x0D, 0x58, 0x7B, 0x7D, 0x73, - 0xA0, 0x57, 0xF2, 0x55, 0x32, 0x47, 0x84, 0x0E, 0x3E, 0x2A, 0xF2, 0xC0, 0x1B, 0x8F, 0x23, 0x4B + 0x40, 0x25, 0x08, 0x56, 0xD8, 0xDA, 0x90, 0x85, 0x9E, 0xDC, 0x1A, 0x0D, 0x58, 0x7B, 0x7D, 0x73, + 0xA0, 0x57, 0xF2, 0x55, 0x32, 0x47, 0x84, 0x0E, 0x3E, 0x2A, 0xF2, 0xC0, 0x1B, 0x8F, 0x23, 0x4B }; size_t license::teamspeak::Anonymous::root_index = 1; shared_ptr license::teamspeak::Anonymous::chain = []() -> shared_ptr { - string error; - auto str = istringstream(string((const char*) default_chain, sizeof(default_chain))); - auto chain = LicenseChain::parse(str, error); - if(!chain) { - cerr << "Failed to load default chain!" << endl; - return nullptr; - } + string error; + auto str = istringstream(string((const char*) default_chain, sizeof(default_chain))); + auto chain = LicenseChain::parse(str, error); + if(!chain) { + cerr << "Failed to load default chain!" << endl; + return nullptr; + } - return chain; + return chain; }(); #define IOERROR(message) \ do {\ error = message;\ - return 0; \ + return 0; \ } while(0) std::shared_ptr LicenseEntry::read(std::istream& stream, std::string& error) { - int baseLength = 42; - streamsize read; - char buffer[42]; - if((read = stream.readsome(buffer, baseLength)) != baseLength) { - if(read == 0) - return nullptr; - else - IOERROR("Could not read new license block"); - } + int baseLength = 42; + streamsize read; + char buffer[42]; + if((read = stream.readsome(buffer, baseLength)) != baseLength) { + if(read == 0) + return nullptr; + else + IOERROR("Could not read new license block"); + } - if(buffer[0] != 0x00) IOERROR("Invalid entry type (" + to_string(buffer[0]) + ")"); + if(buffer[0] != 0x00) IOERROR("Invalid entry type (" + to_string(buffer[0]) + ")"); - shared_ptr result; - switch ((int) buffer[33]) { - case 0x00: - result = make_shared(); - break; - case 0x02: - result = make_shared(); - break; - case 0x03: - result = make_shared(); - break; - case 0x05: - result = make_shared(); - break; - case 0x20: - result = make_shared(); - break; - default: - error = "Invalid license type! (" + to_string((int) buffer[33]) + ")"; - return nullptr; - } + shared_ptr result; + switch ((int) buffer[33]) { + case 0x00: + result = make_shared(); + break; + case 0x02: + result = make_shared(); + break; + case 0x03: + result = make_shared(); + break; + case 0x05: + result = make_shared(); + break; + case 0x20: + result = make_shared(); + break; + default: + error = "Invalid license type! (" + to_string((int) buffer[33]) + ")"; + return nullptr; + } - memcpy(result->key.publicKeyData, &buffer[1], 32); - result->_begin = system_clock::time_point() + seconds(be2le32(buffer, 34) + LicenseEntry::TIMESTAMP_OFFSET); - result->_end = system_clock::time_point() + seconds(be2le32(buffer, 38) + LicenseEntry::TIMESTAMP_OFFSET); + memcpy(result->key.publicKeyData, &buffer[1], 32); + result->_begin = system_clock::time_point() + seconds(be2le32(buffer, 34) + LicenseEntry::TIMESTAMP_OFFSET); + result->_end = system_clock::time_point() + seconds(be2le32(buffer, 38) + LicenseEntry::TIMESTAMP_OFFSET); - if(!result->readContent(stream, error)) return nullptr; - return result; + if(!result->readContent(stream, error)) return nullptr; + return result; } bool LicenseEntry::write(std::ostream& stream, std::string& error) const { - stream << (uint8_t) 0x00; - stream.write((char*) this->key.publicKeyData, 32); - stream.write((char*) &this->_type, 1); + stream << (uint8_t) 0x00; + stream.write((char*) this->key.publicKeyData, 32); + stream.write((char*) &this->_type, 1); - char timeBuffer[8]; - le2be32((uint32_t) (duration_cast(this->_begin.time_since_epoch()).count() - LicenseEntry::TIMESTAMP_OFFSET), timeBuffer, 0); - le2be32((uint32_t) (duration_cast(this->_end.time_since_epoch()).count() - LicenseEntry::TIMESTAMP_OFFSET), timeBuffer, 4); - stream.write(timeBuffer, 8); + char timeBuffer[8]; + le2be32((uint32_t) (duration_cast(this->_begin.time_since_epoch()).count() - LicenseEntry::TIMESTAMP_OFFSET), timeBuffer, 0); + le2be32((uint32_t) (duration_cast(this->_end.time_since_epoch()).count() - LicenseEntry::TIMESTAMP_OFFSET), timeBuffer, 4); + stream.write(timeBuffer, 8); - return this->writeContent(stream, error); + return this->writeContent(stream, error); } std::string LicenseEntry::hash() const { - ostringstream buffer; - string error; - this->write(buffer, error); + ostringstream buffer; + string error; + this->write(buffer, error); - return digest::sha512(buffer.str().substr(1)); + return digest::sha512(buffer.str().substr(1)); } IntermediateLicenseEntry::IntermediateLicenseEntry() : LicenseEntry(LicenseType::INTERMEDIATE) {} bool IntermediateLicenseEntry::readContent(std::istream &stream, std::string &error) { - if(stream.readsome(this->dummy, 4) != 4) IOERROR("Could not read data! (Invalid length!)"); - getline(stream, this->issuer, '\0'); - return true; + if(stream.readsome(this->dummy, 4) != 4) IOERROR("Could not read data! (Invalid length!)"); + getline(stream, this->issuer, '\0'); + return true; } bool IntermediateLicenseEntry::writeContent(std::ostream &ostream, std::string &string1) const { - ostream.write(this->dummy, 4); - ostream << this->issuer; - ostream << (uint8_t) 0; - return true; + ostream.write(this->dummy, 4); + ostream << this->issuer; + ostream << (uint8_t) 0; + return true; } ServerLicenseEntry::ServerLicenseEntry() : LicenseEntry(LicenseType::SERVER) {} bool ServerLicenseEntry::readContent(std::istream &stream, std::string &error) { - if(stream.readsome((char*) &this->licenseType, 1) != 1) IOERROR("Could not read server license type!"); - char buffer[4]; - if(stream.readsome(buffer, 4) != 4) IOERROR("Could not read data! (Invalid length!)"); - this->slots = be2le32(buffer); - getline(stream, this->issuer, '\0'); - return true; + if(stream.readsome((char*) &this->licenseType, 1) != 1) IOERROR("Could not read server license type!"); + char buffer[4]; + if(stream.readsome(buffer, 4) != 4) IOERROR("Could not read data! (Invalid length!)"); + this->slots = be2le32(buffer); + getline(stream, this->issuer, '\0'); + return true; } bool ServerLicenseEntry::writeContent(std::ostream &ostream, std::string &string1) const { - ostream.write((char*) &this->licenseType, 1); - char buffer[4]; - le2be32(this->slots, buffer); - ostream.write(buffer, 4); - ostream.write(this->issuer.data(), this->issuer.length()); - ostream << (uint8_t) 0; - return false; + ostream.write((char*) &this->licenseType, 1); + char buffer[4]; + le2be32(this->slots, buffer); + ostream.write(buffer, 4); + ostream.write(this->issuer.data(), this->issuer.length()); + ostream << (uint8_t) 0; + return false; } CodeLicenseEntry::CodeLicenseEntry() : LicenseEntry(LicenseType::CODE) {} bool CodeLicenseEntry::readContent(std::istream &stream, std::string &error) { - getline(stream, this->issuer, '\0'); - return true; + getline(stream, this->issuer, '\0'); + return true; } bool CodeLicenseEntry::writeContent(std::ostream &ostream, std::string &error) const { - ostream.write(this->issuer.data(), this->issuer.length()); - ostream << (uint8_t) 0; - return true; + ostream.write(this->issuer.data(), this->issuer.length()); + ostream << (uint8_t) 0; + return true; } LicenseSignLicenseEntry::LicenseSignLicenseEntry() : LicenseEntry(LicenseType::LICENSE_SIGN) {} bool LicenseSignLicenseEntry::writeContent(std::ostream &stream, std::string &error) const { return true; } bool LicenseSignLicenseEntry::readContent(std::istream &stream, std::string &error) { - cout << "License read: " << stream.gcount() << " -> " << stream.tellg() << endl; - return true; + cout << "License read: " << stream.gcount() << " -> " << stream.tellg() << endl; + return true; } EphemeralLicenseEntry::EphemeralLicenseEntry() : LicenseEntry(LicenseType::EPHEMERAL) {} @@ -208,175 +208,175 @@ bool EphemeralLicenseEntry::readContent(std::istream &stream, std::string &error bool EphemeralLicenseEntry::writeContent(std::ostream &ostream, std::string &string1) const { return true; } std::shared_ptr LicenseChain::parse(std::istream& stream, std::string& error, bool return_on_error) { - error = ""; + error = ""; - uint8_t chainType; - if(stream.readsome((char*) &chainType, 1) != 1) IOERROR("Invalid stream length!"); - if(chainType != 1) IOERROR("Invalid chain type! (" + to_string(chainType) + ")"); + uint8_t chainType; + if(stream.readsome((char*) &chainType, 1) != 1) IOERROR("Invalid stream length!"); + if(chainType != 1) IOERROR("Invalid chain type! (" + to_string(chainType) + ")"); - deque> entries; - while (stream) { - auto entry = LicenseEntry::read(stream, error); - if(!entry) { - if(error.length() == 0) break; - if(return_on_error) break; - return nullptr; - } - entries.push_back(entry); - } + deque> entries; + while (stream) { + auto entry = LicenseEntry::read(stream, error); + if(!entry) { + if(error.length() == 0) break; + if(return_on_error) break; + return nullptr; + } + entries.push_back(entry); + } - auto result = make_shared(); - result->entries = entries; - return result; + auto result = make_shared(); + result->entries = entries; + return result; } inline std::string to_string(const std::chrono::system_clock::time_point& point) { - auto tp = system_clock::to_time_t(point); - string str = ctime(&tp); - return str.empty() ? str : str.substr(0, str.length() - 1); + auto tp = system_clock::to_time_t(point); + string str = ctime(&tp); + return str.empty() ? str : str.substr(0, str.length() - 1); } void LicenseChain::print() { - int index = 1; - for(const auto& entry : this->entries) { - cout << "Entry " << index ++ << " (Type: " << entry->type() << " | " << type_name(entry->type()) << ")" << endl; + int index = 1; + for(const auto& entry : this->entries) { + cout << "Entry " << index ++ << " (Type: " << entry->type() << " | " << type_name(entry->type()) << ")" << endl; - cout << hex; - cout << " Begin : " << to_string(entry->begin()) << " (" << (duration_cast(entry->begin().time_since_epoch()).count() - LicenseEntry::TIMESTAMP_OFFSET) << ")" << endl; - cout << " End : " << to_string(entry->end()) << " (" << (duration_cast(entry->end().time_since_epoch()).count() - LicenseEntry::TIMESTAMP_OFFSET) << ")" << endl; - cout << " Public key:"; - for(const auto& e : entry->key.publicKeyData) - cout << " " << hex << setfill('0') << setw(2) << (int) e << dec; - cout << endl; + cout << hex; + cout << " Begin : " << to_string(entry->begin()) << " (" << (duration_cast(entry->begin().time_since_epoch()).count() - LicenseEntry::TIMESTAMP_OFFSET) << ")" << endl; + cout << " End : " << to_string(entry->end()) << " (" << (duration_cast(entry->end().time_since_epoch()).count() - LicenseEntry::TIMESTAMP_OFFSET) << ")" << endl; + cout << " Public key:"; + for(const auto& e : entry->key.publicKeyData) + cout << " " << hex << setfill('0') << setw(2) << (int) e << dec; + cout << endl; - if(dynamic_pointer_cast(entry)) { - cout << " Issuer : " << dynamic_pointer_cast(entry)->issuer << endl; - cout << " Slots : " << dynamic_pointer_cast(entry)->unknown << endl; - } else if(dynamic_pointer_cast(entry)) { - cout << " Issuer : " << dynamic_pointer_cast(entry)->issuer << endl; - cout << " Server license type : " << (int) dynamic_pointer_cast(entry)->licenseType << endl; - cout << " Slots : " << dynamic_pointer_cast(entry)->slots << endl; - } else if(dynamic_pointer_cast(entry)){ - cout << " Issuer : " << dynamic_pointer_cast(entry)->issuer << endl; - } - } + if(dynamic_pointer_cast(entry)) { + cout << " Issuer : " << dynamic_pointer_cast(entry)->issuer << endl; + cout << " Slots : " << dynamic_pointer_cast(entry)->unknown << endl; + } else if(dynamic_pointer_cast(entry)) { + cout << " Issuer : " << dynamic_pointer_cast(entry)->issuer << endl; + cout << " Server license type : " << (int) dynamic_pointer_cast(entry)->licenseType << endl; + cout << " Slots : " << dynamic_pointer_cast(entry)->slots << endl; + } else if(dynamic_pointer_cast(entry)){ + cout << " Issuer : " << dynamic_pointer_cast(entry)->issuer << endl; + } + } - auto key = this->generatePublicKey(); - cout << "Public key: " << endl; - hexDump((char*) key.data(), (int) key.length(), (int) key.length(), (int) key.length(), [](string message) { cout << message << endl; }); + auto key = this->generatePublicKey(); + cout << "Public key: " << endl; + hexDump((char*) key.data(), (int) key.length(), (int) key.length(), (int) key.length(), [](string message) { cout << message << endl; }); } std::string LicenseChain::exportChain() { - string error; - ostringstream stream; - stream << (uint8_t) 0x01; - for(const auto& entry : this->entries) - entry->write(stream, error); - return stream.str(); + string error; + ostringstream stream; + stream << (uint8_t) 0x01; + for(const auto& entry : this->entries) + entry->write(stream, error); + return stream.str(); } inline void _ed25519_create_keypair(uint8_t(&public_key)[32], uint8_t(&private_key)[32]) { - uint8_t seed[32]; - ed25519_create_seed(seed); + uint8_t seed[32]; + ed25519_create_seed(seed); - uint8_t buffer_private[64]; /* Because we word with SHA512 we required 64 bytes! */ - ed25519_create_keypair(public_key, buffer_private, seed); - memcpy(private_key, buffer_private, 32); + uint8_t buffer_private[64]; /* Because we word with SHA512 we required 64 bytes! */ + ed25519_create_keypair(public_key, buffer_private, seed); + memcpy(private_key, buffer_private, 32); } void LicenseChain::addIntermediateEntry() { - auto entry = make_shared(); - _ed25519_create_keypair(entry->key.publicKeyData, entry->key.privateKeyData); - entry->key.privateKey = true; - entry->_begin = system_clock::now() - hours(16); - entry->_end = system_clock::now() + hours(16); - entry->issuer = "XXXX"; - entry->unknown = 10; //Max 0x7F - this->entries.push_back(entry); + auto entry = make_shared(); + _ed25519_create_keypair(entry->key.publicKeyData, entry->key.privateKeyData); + entry->key.privateKey = true; + entry->_begin = system_clock::now() - hours(16); + entry->_end = system_clock::now() + hours(16); + entry->issuer = "XXXX"; + entry->unknown = 10; //Max 0x7F + this->entries.push_back(entry); } std::shared_ptr LicenseChain::addServerEntry(ServerLicenseType type, const std::string &issuer, uint32_t slots) { - auto entry = make_shared(); - _ed25519_create_keypair(entry->key.publicKeyData, entry->key.privateKeyData); - entry->key.privateKey = true; - entry->issuer = issuer; - entry->licenseType = type; - entry->slots = slots; - entry->_begin = system_clock::now() - hours(8); - entry->_end = system_clock::now() + hours(8); - this->entries.push_back(entry); - return entry; + auto entry = make_shared(); + _ed25519_create_keypair(entry->key.publicKeyData, entry->key.privateKeyData); + entry->key.privateKey = true; + entry->issuer = issuer; + entry->licenseType = type; + entry->slots = slots; + entry->_begin = system_clock::now() - hours(8); + entry->_end = system_clock::now() + hours(8); + this->entries.push_back(entry); + return entry; } void LicenseChain::addEphemeralEntry() { - auto entry = make_shared(); - _ed25519_create_keypair(entry->key.publicKeyData, entry->key.privateKeyData); - entry->key.privateKey = true; - entry->_begin = system_clock::now() - hours(6); - entry->_end = system_clock::now() + hours(6); - this->entries.push_back(entry); + auto entry = make_shared(); + _ed25519_create_keypair(entry->key.publicKeyData, entry->key.privateKeyData); + entry->key.privateKey = true; + entry->_begin = system_clock::now() - hours(6); + entry->_end = system_clock::now() + hours(6); + this->entries.push_back(entry); } inline ge_p3 import(const char* buffer) { - ge_p3 result{}; - ge_frombytes_negate_vartime(&result, (uint8_t*) buffer); - return result; + ge_p3 result{}; + ge_frombytes_negate_vartime(&result, (uint8_t*) buffer); + return result; } inline string importHash(const std::string& hash) { - uint8_t buffer[64]; //We need to allocate 64 bytes (s[0]+256*s[1]+...+256^63*s[63] as input for sc_reduce (result could max be 2^256 | 32 bytes)) - memset(buffer, 0, 64); + uint8_t buffer[64]; //We need to allocate 64 bytes (s[0]+256*s[1]+...+256^63*s[63] as input for sc_reduce (result could max be 2^256 | 32 bytes)) + memset(buffer, 0, 64); - memcpy(buffer, (void*) hash.data(), 32); - buffer[0] &= 0xF8; - buffer[31] &= 0x3F; - buffer[31] |= 0x40; - sc_reduce(buffer); - return string((char*) buffer, 32); + memcpy(buffer, (void*) hash.data(), 32); + buffer[0] &= 0xF8; + buffer[31] &= 0x3F; + buffer[31] |= 0x40; + sc_reduce(buffer); + return string((char*) buffer, 32); } std::string LicenseChain::generatePublicKey(LicensePublicKey root, int length) const { - auto parent = import((char*) root); - fe_neg(parent.X, parent.X); // undo negate - fe_neg(parent.T, parent.T); // undo negate + auto parent = import((char*) root); + fe_neg(parent.X, parent.X); // undo negate + fe_neg(parent.T, parent.T); // undo negate - for(const auto& entry : this->entries) { - if(length-- == 0) continue; - ge_p3 pKey{}; - ge_frombytes_negate_vartime(&pKey, entry->key.publicKeyData); + for(const auto& entry : this->entries) { + if(length-- == 0) continue; + ge_p3 pKey{}; + ge_frombytes_negate_vartime(&pKey, entry->key.publicKeyData); - ge_cached parentCached{}; - ge_p3_to_cached(&parentCached, &parent); + ge_cached parentCached{}; + ge_p3_to_cached(&parentCached, &parent); - auto clamp = importHash(entry->hash()); + auto clamp = importHash(entry->hash()); - ge_p3 p3_clamp_mul_pKey{}; - ge_p2 p2_clamp_mul_pKey{}; - ge_scalarmult_vartime(&p2_clamp_mul_pKey, (unsigned char *) clamp.data(), &pKey); - ge_p2_to_p3(&p3_clamp_mul_pKey, &p2_clamp_mul_pKey); + ge_p3 p3_clamp_mul_pKey{}; + ge_p2 p2_clamp_mul_pKey{}; + ge_scalarmult_vartime(&p2_clamp_mul_pKey, (unsigned char *) clamp.data(), &pKey); + ge_p2_to_p3(&p3_clamp_mul_pKey, &p2_clamp_mul_pKey); - //----- | ----- - ge_p1p1 a{}; - ge_add(&a, &p3_clamp_mul_pKey, &parentCached); + //----- | ----- + ge_p1p1 a{}; + ge_add(&a, &p3_clamp_mul_pKey, &parentCached); - ge_p3 r2{}; - ge_p1p1_to_p3(&r2, &a); + ge_p3 r2{}; + ge_p1p1_to_p3(&r2, &a); - parent = r2; - } + parent = r2; + } - char buf[32]; - ge_p3_tobytes((uint8_t*) buf, &parent); - return string(buf, 32); + char buf[32]; + ge_p3_tobytes((uint8_t*) buf, &parent); + return string(buf, 32); } std::string LicenseChain::generatePrivateKey(uint8_t *root, int begin) const { - uint8_t buffer[32]; - memcpy(buffer, root, 32); - for(int index = begin; index < this->entries.size(); index++) { - assert(this->entries[index]->key.privateKey); - sc_muladd(buffer, this->entries[index]->key.privateKeyData, (uint8_t*) importHash(this->entries[index]->hash()).data(), buffer); - } - return string((char*) buffer, 32); + uint8_t buffer[32]; + memcpy(buffer, root, 32); + for(int index = begin; index < this->entries.size(); index++) { + assert(this->entries[index]->key.privateKey); + sc_muladd(buffer, this->entries[index]->key.privateKeyData, (uint8_t*) importHash(this->entries[index]->hash()).data(), buffer); + } + return string((char*) buffer, 32); } \ No newline at end of file diff --git a/src/License.h b/src/License.h index b676407..70b1167 100644 --- a/src/License.h +++ b/src/License.h @@ -6,192 +6,192 @@ #include namespace license { - namespace teamspeak { - class LicenseChain; - enum LicenseType { - INTERMEDIATE = 0x00, - WEBSIDE = 0x01, - SERVER = 0x02, - CODE = 0x03, - TOKEN = 0x04, - LICENSE_SIGN = 0x05, - MY_TS_ID_SIGN = 0x06, - EPHEMERAL = 0x20 - }; - inline std::string type_name(LicenseType type) { - switch (type) { - case LicenseType::INTERMEDIATE: - return "Intermediate"; - case LicenseType::WEBSIDE: - return "Website"; - case LicenseType::SERVER: - return "Server"; - case LicenseType::CODE: - return "Code"; - case LicenseType::LICENSE_SIGN: - return "LicenseSign"; - case LicenseType::MY_TS_ID_SIGN: - return "MyTsIdSign"; - case LicenseType::EPHEMERAL: - return "Ephemeral"; - default: - return "Unknown"; - } - } + namespace teamspeak { + class LicenseChain; + enum LicenseType { + INTERMEDIATE = 0x00, + WEBSIDE = 0x01, + SERVER = 0x02, + CODE = 0x03, + TOKEN = 0x04, + LICENSE_SIGN = 0x05, + MY_TS_ID_SIGN = 0x06, + EPHEMERAL = 0x20 + }; + inline std::string type_name(LicenseType type) { + switch (type) { + case LicenseType::INTERMEDIATE: + return "Intermediate"; + case LicenseType::WEBSIDE: + return "Website"; + case LicenseType::SERVER: + return "Server"; + case LicenseType::CODE: + return "Code"; + case LicenseType::LICENSE_SIGN: + return "LicenseSign"; + case LicenseType::MY_TS_ID_SIGN: + return "MyTsIdSign"; + case LicenseType::EPHEMERAL: + return "Ephemeral"; + default: + return "Unknown"; + } + } - enum ServerLicenseType : uint8_t { - SERVER_LICENSE_NONE, - SERVER_LICENSE_OFFLINE, - SERVER_LICENSE_SDK, - SERVER_LICENSE_SDKOFFLINE, - SERVER_LICENSE_NPL, - SERVER_LICENSE_ATHP, - SERVER_LICENSE_AAL, - SERVER_LICENSE_DEFAULT, - }; + enum ServerLicenseType : uint8_t { + SERVER_LICENSE_NONE, + SERVER_LICENSE_OFFLINE, + SERVER_LICENSE_SDK, + SERVER_LICENSE_SDKOFFLINE, + SERVER_LICENSE_NPL, + SERVER_LICENSE_ATHP, + SERVER_LICENSE_AAL, + SERVER_LICENSE_DEFAULT, + }; - struct LicenseKey { - bool privateKey = false; - uint8_t privateKeyData[32] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + struct LicenseKey { + bool privateKey = false; + uint8_t privateKeyData[32] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t publicKeyData[32] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - }; + }; - typedef uint8_t LicensePublicKey[32]; - class LicenseEntry { - static constexpr int64_t TIMESTAMP_OFFSET = 0x50e22700; - friend class LicenseChain; - public: - LicenseEntry(LicenseType type) : _type(type) {} - ~LicenseEntry() {} + typedef uint8_t LicensePublicKey[32]; + class LicenseEntry { + static constexpr int64_t TIMESTAMP_OFFSET = 0x50e22700; + friend class LicenseChain; + public: + LicenseEntry(LicenseType type) : _type(type) {} + ~LicenseEntry() {} - virtual LicenseType type() const { return this->_type; } + virtual LicenseType type() const { return this->_type; } - static std::shared_ptr read(std::istream&, std::string&); - virtual bool write(std::ostream&, std::string&) const ; + static std::shared_ptr read(std::istream&, std::string&); + virtual bool write(std::ostream&, std::string&) const ; - std::string hash() const; + std::string hash() const; - std::chrono::system_clock::time_point begin() const { return this->_begin; } - std::chrono::system_clock::time_point end() const { return this->_end; } + std::chrono::system_clock::time_point begin() const { return this->_begin; } + std::chrono::system_clock::time_point end() const { return this->_end; } - void begin(const std::chrono::system_clock::time_point& begin) { this->_begin = begin; } - void end(const std::chrono::system_clock::time_point& end) { this->_end = end; } + void begin(const std::chrono::system_clock::time_point& begin) { this->_begin = begin; } + void end(const std::chrono::system_clock::time_point& end) { this->_end = end; } - template - Unit lifetime() { return std::chrono::duration_cast(this->_end - this->_begin); } + template + Unit lifetime() { return std::chrono::duration_cast(this->_end - this->_begin); } - template - void lifetime(const Unit& lifetime, const std::chrono::system_clock::time_point& begin = std::chrono::system_clock::now()) { - this->_begin = begin; - this->_end = begin + lifetime; - } - protected: - virtual bool readContent(std::istream&, std::string&) = 0; - virtual bool writeContent(std::ostream&, std::string&) const = 0; + template + void lifetime(const Unit& lifetime, const std::chrono::system_clock::time_point& begin = std::chrono::system_clock::now()) { + this->_begin = begin; + this->_end = begin + lifetime; + } + protected: + virtual bool readContent(std::istream&, std::string&) = 0; + virtual bool writeContent(std::ostream&, std::string&) const = 0; - LicenseKey key; - LicenseType _type; - std::chrono::system_clock::time_point _begin; - std::chrono::system_clock::time_point _end; - }; + LicenseKey key; + LicenseType _type; + std::chrono::system_clock::time_point _begin; + std::chrono::system_clock::time_point _end; + }; - class IntermediateLicenseEntry : public LicenseEntry { - public: - IntermediateLicenseEntry(); + class IntermediateLicenseEntry : public LicenseEntry { + public: + IntermediateLicenseEntry(); - std::string issuer; - union { - uint32_t unknown; - char dummy[4]; - }; - protected: - bool readContent(std::istream &istream1, std::string &string1) override; - bool writeContent(std::ostream &ostream1, std::string &string1) const override; - }; + std::string issuer; + union { + uint32_t unknown; + char dummy[4]; + }; + protected: + bool readContent(std::istream &istream1, std::string &string1) override; + bool writeContent(std::ostream &ostream1, std::string &string1) const override; + }; - class ServerLicenseEntry : public LicenseEntry { - public: - ServerLicenseEntry(); + class ServerLicenseEntry : public LicenseEntry { + public: + ServerLicenseEntry(); - ServerLicenseType licenseType; - std::string issuer; - uint32_t slots; - protected: - bool readContent(std::istream &stream, std::string &error) override; - bool writeContent(std::ostream &stream, std::string &error) const override; - }; + ServerLicenseType licenseType; + std::string issuer; + uint32_t slots; + protected: + bool readContent(std::istream &stream, std::string &error) override; + bool writeContent(std::ostream &stream, std::string &error) const override; + }; - class CodeLicenseEntry : public LicenseEntry { - public: - CodeLicenseEntry(); + class CodeLicenseEntry : public LicenseEntry { + public: + CodeLicenseEntry(); - std::string issuer; - protected: - bool readContent(std::istream &stream, std::string &error) override; - bool writeContent(std::ostream &stream, std::string &error) const override; - }; + std::string issuer; + protected: + bool readContent(std::istream &stream, std::string &error) override; + bool writeContent(std::ostream &stream, std::string &error) const override; + }; - class LicenseSignLicenseEntry : public LicenseEntry { - public: - LicenseSignLicenseEntry(); + class LicenseSignLicenseEntry : public LicenseEntry { + public: + LicenseSignLicenseEntry(); - protected: - bool readContent(std::istream &stream, std::string &error) override; - bool writeContent(std::ostream &stream, std::string &error) const override; - }; + protected: + bool readContent(std::istream &stream, std::string &error) override; + bool writeContent(std::ostream &stream, std::string &error) const override; + }; - class EphemeralLicenseEntry : public LicenseEntry { - public: - EphemeralLicenseEntry(); - protected: - bool readContent(std::istream &stream, std::string &error) override; - bool writeContent(std::ostream &stream, std::string &error) const override; - }; + class EphemeralLicenseEntry : public LicenseEntry { + public: + EphemeralLicenseEntry(); + protected: + bool readContent(std::istream &stream, std::string &error) override; + bool writeContent(std::ostream &stream, std::string &error) const override; + }; - extern LicensePublicKey public_root; - extern LicensePublicKey public_tea_root; - extern LicensePublicKey private_tea_root; + extern LicensePublicKey public_root; + extern LicensePublicKey public_tea_root; + extern LicensePublicKey private_tea_root; - class LicenseChain { - public: - static std::shared_ptr parse(std::istream&, std::string&, bool return_on_error = false); - inline static std::shared_ptr parse(const std::string& license, std::string& error, bool return_on_error = false) { - std::istringstream s(license); - return LicenseChain::parse(s, error, return_on_error); - } + class LicenseChain { + public: + static std::shared_ptr parse(std::istream&, std::string&, bool return_on_error = false); + inline static std::shared_ptr parse(const std::string& license, std::string& error, bool return_on_error = false) { + std::istringstream s(license); + return LicenseChain::parse(s, error, return_on_error); + } - LicenseChain() {} - ~LicenseChain() {} + LicenseChain() {} + ~LicenseChain() {} - std::shared_ptr copy() { - auto result = std::make_shared(); - result->entries = this->entries; - return result; - } + std::shared_ptr copy() { + auto result = std::make_shared(); + result->entries = this->entries; + return result; + } - void print(); - std::string exportChain(); + void print(); + std::string exportChain(); - void addEphemeralEntry(); - void addIntermediateEntry(); - std::shared_ptr addServerEntry(ServerLicenseType, const std::string& issuer, uint32_t slots); - void addEntry(const std::shared_ptr& entry) { this->entries.push_back(entry); } + void addEphemeralEntry(); + void addIntermediateEntry(); + std::shared_ptr addServerEntry(ServerLicenseType, const std::string& issuer, uint32_t slots); + void addEntry(const std::shared_ptr& entry) { this->entries.push_back(entry); } - /* - * Attention! Root must be compressd - */ - std::string generatePublicKey(LicensePublicKey = public_root, int length = -1) const; - std::string generatePrivateKey(LicensePublicKey = private_tea_root, int begin = 0) const; + /* + * Attention! Root must be compressd + */ + std::string generatePublicKey(LicensePublicKey = public_root, int length = -1) const; + std::string generatePrivateKey(LicensePublicKey = private_tea_root, int begin = 0) const; - std::deque> entries; - private: - }; + std::deque> entries; + private: + }; - namespace Anonymous { - extern std::shared_ptr chain; //Thu Jun 1 00:00:00 2017 - Sat Sep 1 00:00:00 2018 - extern LicensePublicKey root_key; - extern size_t root_index; - } + namespace Anonymous { + extern std::shared_ptr chain; //Thu Jun 1 00:00:00 2017 - Sat Sep 1 00:00:00 2018 + extern LicensePublicKey root_key; + extern size_t root_index; + } - } + } } \ No newline at end of file diff --git a/src/PermissionManager.cpp b/src/PermissionManager.cpp index 2ea5e43..413bd1e 100644 --- a/src/PermissionManager.cpp +++ b/src/PermissionManager.cpp @@ -650,37 +650,37 @@ std::shared_ptr PermissionTypeEntry::unknown = make_shared< vector> permission_id_map; void permission::setup_permission_resolve() { - permission_id_map.resize(permission::permission_id_max); + permission_id_map.resize(permission::permission_id_max); - for(auto& permission : availablePermissions) { - if(!permission->clientSupported || permission->type < 0 || permission->type > permission::permission_id_max) - continue; - permission_id_map[permission->type] = permission; - } + for(auto& permission : availablePermissions) { + if(!permission->clientSupported || permission->type < 0 || permission->type > permission::permission_id_max) + continue; + permission_id_map[permission->type] = permission; + } - /* fix "holes" as well set the permission id 0 (unknown) */ - for(auto& permission : permission_id_map) { - if(permission) - continue; - permission = PermissionTypeEntry::unknown; - } + /* fix "holes" as well set the permission id 0 (unknown) */ + for(auto& permission : permission_id_map) { + if(permission) + continue; + permission = PermissionTypeEntry::unknown; + } } std::shared_ptr permission::resolvePermissionData(PermissionType type) { - if((type & PERM_ID_GRANT) > 0) - type &= ~PERM_ID_GRANT; + if((type & PERM_ID_GRANT) > 0) + type &= ~PERM_ID_GRANT; - assert(!permission_id_map.empty()); - if(type < 0 || type >= permission::permission_id_max) - return PermissionTypeEntry::unknown; + assert(!permission_id_map.empty()); + if(type < 0 || type >= permission::permission_id_max) + return PermissionTypeEntry::unknown; return permission_id_map[type]; } std::shared_ptr permission::resolvePermissionData(const std::string& name) { for(auto& elm : availablePermissions) - if(elm->name == name || elm->grant_name == name) - return elm; + if(elm->name == name || elm->grant_name == name) + return elm; return PermissionTypeEntry::unknown; } @@ -731,18 +731,18 @@ bool PermissionManager::setPermission(PermissionType type, PermissionValue value } bool PermissionManager::setPermission(ts::permission::PermissionType type, ts::permission::PermissionValue value, const std::shared_ptr &channel, bool negated, bool skiped) { - auto list = this->getPermission(type, channel, false); - if(list.empty()) - list.push_back(registerPermission(type, value, channel, PERM_FLAG_PUBLIC)); + auto list = this->getPermission(type, channel, false); + if(list.empty()) + list.push_back(registerPermission(type, value, channel, PERM_FLAG_PUBLIC)); - list.front()->value = value; - list.front()->flag_negate = negated; - list.front()->flag_skip = skiped; + list.front()->value = value; + list.front()->flag_negate = negated; + list.front()->flag_skip = skiped; - for(const auto& elm : this->updateHandler) - elm(list.front()); + for(const auto& elm : this->updateHandler) + elm(list.front()); - return true; + return true; } bool PermissionManager::setPermissionGranted(PermissionType type, PermissionValue value, const std::shared_ptr& channel) { @@ -771,17 +771,17 @@ void PermissionManager::deletePermission(PermissionType type, const std::shared_ std::deque> PermissionManager::getPermission(PermissionType type, const std::shared_ptr& channel, bool testGlobal) { std::deque> res; - std::shared_ptr channel_permission; - std::shared_ptr global_permission; + std::shared_ptr channel_permission; + std::shared_ptr global_permission; for(const auto &perm : this->permissions) - if(perm->type->type == type) { - if(perm->channel == channel) - channel_permission = perm; - else if(!perm->channel && testGlobal) - global_permission = perm; - } - if(channel_permission) res.push_back(channel_permission); - if(global_permission) res.push_back(global_permission); + if(perm->type->type == type) { + if(perm->channel == channel) + channel_permission = perm; + else if(!perm->channel && testGlobal) + global_permission = perm; + } + if(channel_permission) res.push_back(channel_permission); + if(global_permission) res.push_back(global_permission); return res; } @@ -798,64 +798,64 @@ std::vector> PermissionManager::allPermissions() { } std::deque> PermissionManager::all_channel_specific_permissions() { - std::deque> result; + std::deque> result; - for(const auto& permission : this->permissions) - if(permission->channel) - result.push_back(permission); + for(const auto& permission : this->permissions) + if(permission->channel) + result.push_back(permission); - return result; + return result; } std::deque> PermissionManager::all_channel_unspecific_permissions() { - std::deque> result; + std::deque> result; - for(const auto& permission : this->permissions) - if(!permission->channel) - result.push_back(permission); + for(const auto& permission : this->permissions) + if(!permission->channel) + result.push_back(permission); - return result; + return result; } teamspeak::MapType teamspeak::unmapping; teamspeak::MapType teamspeak::mapping; teamspeak::MapType build_mapping(){ - return { - {teamspeak::GENERAL, { - {"b_virtualserver_modify_port", {"b_virtualserver_modify_port", "b_virtualserver_modify_host"}}, - {"i_client_max_clones_uid", {"i_client_max_clones_uid", "i_client_max_clones_ip", "i_client_max_clones_hwid"}}, + return { + {teamspeak::GENERAL, { + {"b_virtualserver_modify_port", {"b_virtualserver_modify_port", "b_virtualserver_modify_host"}}, + {"i_client_max_clones_uid", {"i_client_max_clones_uid", "i_client_max_clones_ip", "i_client_max_clones_hwid"}}, {"b_client_ignore_bans", {"b_client_ignore_bans", "b_client_ignore_vpn"}}, - {"b_client_ban_list", {"b_client_ban_list", "b_client_ban_list_global"}}, + {"b_client_ban_list", {"b_client_ban_list", "b_client_ban_list_global"}}, - //Permissions which TeaSpeak has but TeamSpeak not - {"", {"b_virtualserver_modify_music_bot_limit"}}, - {"", {"b_client_music_channel_list"}}, - {"", {"b_client_music_server_list"}}, - {"", {"i_client_music_info"}}, - {"", {"i_client_music_needed_info"}}, + //Permissions which TeaSpeak has but TeamSpeak not + {"", {"b_virtualserver_modify_music_bot_limit"}}, + {"", {"b_client_music_channel_list"}}, + {"", {"b_client_music_server_list"}}, + {"", {"i_client_music_info"}}, + {"", {"i_client_music_needed_info"}}, - {"", {"b_client_ban_edit"}}, - {"", {"b_client_ban_edit_global"}}, - {"", {"b_client_ban_create_global"}}, - {"", {"b_client_ban_delete_own_global"}}, - {"", {"b_client_ban_delete_global"}}, + {"", {"b_client_ban_edit"}}, + {"", {"b_client_ban_edit_global"}}, + {"", {"b_client_ban_create_global"}}, + {"", {"b_client_ban_delete_own_global"}}, + {"", {"b_client_ban_delete_global"}}, - {"", {"b_client_even_textmessage_send"}}, - {"", {"b_client_enforce_valid_hwid"}}, - {"", {"b_client_allow_invalid_packet"}}, - {"", {"b_client_allow_invalid_badges"}}, + {"", {"b_client_even_textmessage_send"}}, + {"", {"b_client_enforce_valid_hwid"}}, + {"", {"b_client_allow_invalid_packet"}}, + {"", {"b_client_allow_invalid_badges"}}, - {"", {"b_client_music_create"}}, - {"", {"b_client_music_delete_own"}}, + {"", {"b_client_music_create"}}, + {"", {"b_client_music_delete_own"}}, - {"", {"i_client_music_limit"}}, - {"", {"i_client_music_needed_delete_power"}}, - {"", {"i_client_music_delete_power"}}, - {"", {"i_client_music_play_power"}}, - {"", {"i_client_music_needed_play_power"}}, - {"", {"i_client_music_rename_power"}}, - {"", {"i_client_music_needed_rename_power"}}, + {"", {"i_client_music_limit"}}, + {"", {"i_client_music_needed_delete_power"}}, + {"", {"i_client_music_delete_power"}}, + {"", {"i_client_music_play_power"}}, + {"", {"i_client_music_needed_play_power"}}, + {"", {"i_client_music_rename_power"}}, + {"", {"i_client_music_needed_rename_power"}}, {"", {"b_client_use_bbcode_any"}}, {"", {"b_client_use_bbcode_url"}}, @@ -865,72 +865,72 @@ teamspeak::MapType build_mapping(){ {"", {"i_channel_view_power"}}, {"", {"i_channel_needed_view_power"}}, - {"", {"i_client_max_channels"}}, - {"", {"i_client_max_temporary_channels"}}, - {"", {"i_client_max_semi_channels"}}, - {"", {"i_client_max_permanent_channels"}}, + {"", {"i_client_max_channels"}}, + {"", {"i_client_max_temporary_channels"}}, + {"", {"i_client_max_semi_channels"}}, + {"", {"i_client_max_permanent_channels"}}, - {"", {"b_virtualserver_modify_default_messages"}}, + {"", {"b_virtualserver_modify_default_messages"}}, - {"b_client_ban_list", {"b_client_ban_list", "b_client_ban_trigger_list"}}, + {"b_client_ban_list", {"b_client_ban_list", "b_client_ban_trigger_list"}}, {"b_virtualserver_select", {"b_virtualserver_select", "b_virtualserver_select_godmode"}}, - {"b_virtualserver_modify_default_servergroup", {"b_virtualserver_modify_default_servergroup", "b_virtualserver_modify_default_musicgroup"}}, + {"b_virtualserver_modify_default_servergroup", {"b_virtualserver_modify_default_servergroup", "b_virtualserver_modify_default_musicgroup"}}, - {"b_client_ban_create", {"b_client_ban_create", "b_client_ban_name", "b_client_ban_ip", "b_client_ban_hwid"}} - }, - }, - {teamspeak::SERVER, { - {"i_group_modify_power", {"i_server_group_modify_power", "i_channel_group_modify_power", "i_displayed_group_modify_power"}}, - {"i_group_member_add_power", {"i_server_group_member_add_power", "i_channel_group_member_add_power", "i_displayed_group_member_add_power"}}, - {"i_group_member_remove_power", {"i_server_group_member_remove_power", "i_channel_group_member_remove_power", "i_displayed_group_member_remove_power"}}, - {"i_group_needed_modify_power", {"i_server_group_needed_modify_power", "i_channel_group_needed_modify_power", "i_displayed_group_needed_modify_power"}}, - {"i_group_needed_member_add_power", {"i_server_group_needed_member_add_power", "i_channel_group_needed_member_add_power", "i_displayed_group_needed_member_add_power"}}, - {"i_group_needed_member_remove_power", {"i_server_group_needed_member_remove_power", "i_channel_group_needed_member_remove_power", "i_displayed_group_needed_member_remove_power"}}, - }, - }, - {teamspeak::CLIENT, { - {"i_group_modify_power", {"i_server_group_modify_power", "i_channel_group_modify_power", "i_displayed_group_modify_power"}}, - {"i_group_member_add_power", {"i_server_group_member_add_power", "i_channel_group_member_add_power", "i_displayed_group_member_add_power"}}, - {"i_group_member_remove_power", {"i_server_group_member_remove_power", "i_channel_group_member_remove_power", "i_displayed_group_member_remove_power"}}, - {"i_group_needed_modify_power", {"i_server_group_needed_modify_power", "i_channel_group_needed_modify_power", "i_displayed_group_needed_modify_power"}}, - {"i_group_needed_member_add_power", {"i_server_group_needed_member_add_power", "i_channel_group_needed_member_add_power", "i_displayed_group_needed_member_add_power"}}, - {"i_group_needed_member_remove_power", {"i_server_group_needed_member_remove_power", "i_channel_group_needed_member_remove_power", "i_displayed_group_needed_member_remove_power"}}, - }, - }, - {teamspeak::CHANNEL, { - {"i_group_modify_power", {"i_channel_group_modify_power", "i_displayed_group_modify_power"}}, - {"i_group_member_add_power", {"i_channel_group_member_add_power", "i_displayed_group_member_add_power"}}, - {"i_group_member_remove_power", {"i_channel_group_member_remove_power", "i_displayed_group_member_remove_power"}}, - {"i_group_needed_modify_power", {"i_channel_group_needed_modify_power", "i_displayed_group_needed_modify_power"}}, - {"i_group_needed_member_add_power", {"i_channel_group_needed_member_add_power", "i_displayed_group_needed_member_add_power"}}, - {"i_group_needed_member_remove_power", {"i_channel_group_needed_member_remove_power", "i_displayed_group_needed_member_remove_power"}}, - }, - }, - }; + {"b_client_ban_create", {"b_client_ban_create", "b_client_ban_name", "b_client_ban_ip", "b_client_ban_hwid"}} + }, + }, + {teamspeak::SERVER, { + {"i_group_modify_power", {"i_server_group_modify_power", "i_channel_group_modify_power", "i_displayed_group_modify_power"}}, + {"i_group_member_add_power", {"i_server_group_member_add_power", "i_channel_group_member_add_power", "i_displayed_group_member_add_power"}}, + {"i_group_member_remove_power", {"i_server_group_member_remove_power", "i_channel_group_member_remove_power", "i_displayed_group_member_remove_power"}}, + {"i_group_needed_modify_power", {"i_server_group_needed_modify_power", "i_channel_group_needed_modify_power", "i_displayed_group_needed_modify_power"}}, + {"i_group_needed_member_add_power", {"i_server_group_needed_member_add_power", "i_channel_group_needed_member_add_power", "i_displayed_group_needed_member_add_power"}}, + {"i_group_needed_member_remove_power", {"i_server_group_needed_member_remove_power", "i_channel_group_needed_member_remove_power", "i_displayed_group_needed_member_remove_power"}}, + }, + }, + {teamspeak::CLIENT, { + {"i_group_modify_power", {"i_server_group_modify_power", "i_channel_group_modify_power", "i_displayed_group_modify_power"}}, + {"i_group_member_add_power", {"i_server_group_member_add_power", "i_channel_group_member_add_power", "i_displayed_group_member_add_power"}}, + {"i_group_member_remove_power", {"i_server_group_member_remove_power", "i_channel_group_member_remove_power", "i_displayed_group_member_remove_power"}}, + {"i_group_needed_modify_power", {"i_server_group_needed_modify_power", "i_channel_group_needed_modify_power", "i_displayed_group_needed_modify_power"}}, + {"i_group_needed_member_add_power", {"i_server_group_needed_member_add_power", "i_channel_group_needed_member_add_power", "i_displayed_group_needed_member_add_power"}}, + {"i_group_needed_member_remove_power", {"i_server_group_needed_member_remove_power", "i_channel_group_needed_member_remove_power", "i_displayed_group_needed_member_remove_power"}}, + }, + }, + {teamspeak::CHANNEL, { + {"i_group_modify_power", {"i_channel_group_modify_power", "i_displayed_group_modify_power"}}, + {"i_group_member_add_power", {"i_channel_group_member_add_power", "i_displayed_group_member_add_power"}}, + {"i_group_member_remove_power", {"i_channel_group_member_remove_power", "i_displayed_group_member_remove_power"}}, + {"i_group_needed_modify_power", {"i_channel_group_needed_modify_power", "i_displayed_group_needed_modify_power"}}, + {"i_group_needed_member_add_power", {"i_channel_group_needed_member_add_power", "i_displayed_group_needed_member_add_power"}}, + {"i_group_needed_member_remove_power", {"i_channel_group_needed_member_remove_power", "i_displayed_group_needed_member_remove_power"}}, + }, + }, + }; }; inline teamspeak::MapType build_unmapping() { teamspeak::MapType result; - for(const auto& map : teamspeak::mapping) { - for(const auto& entry : map.second) { - for(const auto& key : entry.second) { + for(const auto& map : teamspeak::mapping) { + for(const auto& entry : map.second) { + for(const auto& key : entry.second) { auto& m = result[map.first]; auto it = m.find(key); if(it == m.end()) m.insert({key, {}}); it = m.find(key); if(!entry.first.empty()) it->second.push_back(entry.first); - } - } - } + } + } + } - return result; + return result; }; inline void init_mapping() { - if(teamspeak::mapping.empty()) teamspeak::mapping = build_mapping(); - if(teamspeak::unmapping.empty()) teamspeak::unmapping = build_unmapping(); + if(teamspeak::mapping.empty()) teamspeak::mapping = build_mapping(); + if(teamspeak::unmapping.empty()) teamspeak::unmapping = build_unmapping(); } template @@ -946,22 +946,22 @@ inline deque mmget(teamspeak::MapType& map, teamspeak::GroupType type, c } inline std::deque map_entry(std::string key, teamspeak::GroupType type, teamspeak::MapType& map_table) { - init_mapping(); + init_mapping(); - if(key.find("_needed_modify_power_") == 1) { - key = key.substr(strlen("x_needed_modify_power_")); + if(key.find("_needed_modify_power_") == 1) { + key = key.substr(strlen("x_needed_modify_power_")); - deque result; - if(map_table[type].count("i_" + key) > 0 || map_table[teamspeak::GroupType::GENERAL].count("i_" + key) > 0) result = mmget(map_table, type, "i_" + key) + mmget(map_table, teamspeak::GroupType::GENERAL, "i_" + key); - else if(map_table[type].count("b_" + key) > 0 || map_table[teamspeak::GroupType::GENERAL].count("b_" + key) > 0) result = mmget(map_table, type, "b_" + key) + mmget(map_table, teamspeak::GroupType::GENERAL, "b_" + key); - else result = {"x_" + key}; + deque result; + if(map_table[type].count("i_" + key) > 0 || map_table[teamspeak::GroupType::GENERAL].count("i_" + key) > 0) result = mmget(map_table, type, "i_" + key) + mmget(map_table, teamspeak::GroupType::GENERAL, "i_" + key); + else if(map_table[type].count("b_" + key) > 0 || map_table[teamspeak::GroupType::GENERAL].count("b_" + key) > 0) result = mmget(map_table, type, "b_" + key) + mmget(map_table, teamspeak::GroupType::GENERAL, "b_" + key); + else result = {"x_" + key}; - for(auto& entry : result) - entry = "i_needed_modify_power_" + entry.substr(2); - return result; - } - if(map_table[type].count(key) > 0 || map_table[teamspeak::GroupType::GENERAL].count(key) > 0) return mmget(map_table, type, key) + mmget(map_table, teamspeak::GroupType::GENERAL, key); - return {key}; + for(auto& entry : result) + entry = "i_needed_modify_power_" + entry.substr(2); + return result; + } + if(map_table[type].count(key) > 0 || map_table[teamspeak::GroupType::GENERAL].count(key) > 0) return mmget(map_table, type, key) + mmget(map_table, teamspeak::GroupType::GENERAL, key); + return {key}; } std::deque teamspeak::map_key(std::string key, GroupType type) { @@ -969,7 +969,7 @@ std::deque teamspeak::map_key(std::string key, GroupType type) { } std::deque teamspeak::unmap_key(std::string key, GroupType type) { - return map_entry(key, type, teamspeak::unmapping); + return map_entry(key, type, teamspeak::unmapping); } @@ -1057,465 +1057,465 @@ deque update::migrate = { }; v2::PermissionManager::PermissionManager() { - memset(this->block_use_count, 0, sizeof(this->block_use_count)); - memset(this->block_containers, 0, sizeof(this->block_containers)); + memset(this->block_use_count, 0, sizeof(this->block_use_count)); + memset(this->block_containers, 0, sizeof(this->block_containers)); } v2::PermissionManager::~PermissionManager() { - for(auto& block : this->block_containers) - delete block; + for(auto& block : this->block_containers) + delete block; } void v2::PermissionManager::load_permission(const ts::permission::PermissionType &permission, const ts::permission::v2::PermissionValues &values, bool flag_skip, bool flag_negate, bool flag_value, bool flag_grant) { - if(permission < 0 || permission >= PermissionType::permission_id_max) - return; + if(permission < 0 || permission >= PermissionType::permission_id_max) + return; - const auto block = this->calculate_block(permission); - this->ref_allocate_block(block); + const auto block = this->calculate_block(permission); + this->ref_allocate_block(block); - auto& data = this->block_containers[block]->permissions[this->calculate_block_index(permission)]; - data.values = values; - data.flags.database_reference = true; - data.flags.skip = flag_skip; - data.flags.negate = flag_negate; - data.flags.value_set = flag_value; - data.flags.grant_set = flag_grant; - this->unref_block(block); + auto& data = this->block_containers[block]->permissions[this->calculate_block_index(permission)]; + data.values = values; + data.flags.database_reference = true; + data.flags.skip = flag_skip; + data.flags.negate = flag_negate; + data.flags.value_set = flag_value; + data.flags.grant_set = flag_grant; + this->unref_block(block); } void v2::PermissionManager::load_permission(const ts::permission::PermissionType &permission, const ts::permission::v2::PermissionValues &values, ChannelId channel_id, bool flag_skip, bool flag_negate, bool flag_value, bool flag_grant) { - if(permission < 0 || permission >= PermissionType::permission_id_max) - return; + if(permission < 0 || permission >= PermissionType::permission_id_max) + return; - unique_lock channel_perm_lock(this->channel_list_lock); - ChannelPermissionContainer* permission_container = nullptr; - for(auto& entry : this->_channel_permissions) - if(entry->permission == permission && entry->channel_id == channel_id) { - permission_container = &*entry; - break; - } + unique_lock channel_perm_lock(this->channel_list_lock); + ChannelPermissionContainer* permission_container = nullptr; + for(auto& entry : this->_channel_permissions) + if(entry->permission == permission && entry->channel_id == channel_id) { + permission_container = &*entry; + break; + } - if(!permission_container) { - auto container = make_unique(); - container->permission = permission; - container->channel_id = channel_id; - permission_container = &*container; - this->_channel_permissions.push_back(std::move(container)); + if(!permission_container) { + auto container = make_unique(); + container->permission = permission; + container->channel_id = channel_id; + permission_container = &*container; + this->_channel_permissions.push_back(std::move(container)); - /* now set the channel flag for that permission */ - const auto block = this->calculate_block(permission); - this->ref_allocate_block(block); + /* now set the channel flag for that permission */ + const auto block = this->calculate_block(permission); + this->ref_allocate_block(block); - auto& data = this->block_containers[block]->permissions[this->calculate_block_index(permission)]; - data.flags.channel_specific = true; - this->unref_block(block); - } + auto& data = this->block_containers[block]->permissions[this->calculate_block_index(permission)]; + data.flags.channel_specific = true; + this->unref_block(block); + } - permission_container->values = values; - permission_container->flags.database_reference = true; - permission_container->flags.skip = flag_skip; - permission_container->flags.negate = flag_negate; - permission_container->flags.value_set = flag_value; - permission_container->flags.grant_set = flag_grant; + permission_container->values = values; + permission_container->flags.database_reference = true; + permission_container->flags.skip = flag_skip; + permission_container->flags.negate = flag_negate; + permission_container->flags.value_set = flag_value; + permission_container->flags.grant_set = flag_grant; } static constexpr v2::PermissionFlags empty_flags = {false, false, false, false, false, false, 0}; const v2::PermissionFlags v2::PermissionManager::permission_flags(const ts::permission::PermissionType &permission) { - if(permission < 0 || permission >= PermissionType::permission_id_max) - return empty_flags; + if(permission < 0 || permission >= PermissionType::permission_id_max) + return empty_flags; - const auto block = this->calculate_block(permission); - if(!this->ref_block(block)) - return empty_flags; + const auto block = this->calculate_block(permission); + if(!this->ref_block(block)) + return empty_flags; - PermissionFlags result{this->block_containers[block]->permissions[this->calculate_block_index(permission)].flags}; - this->unref_block(block); - return result; + PermissionFlags result{this->block_containers[block]->permissions[this->calculate_block_index(permission)].flags}; + this->unref_block(block); + return result; } const v2::PermissionValues v2::PermissionManager::permission_values(const ts::permission::PermissionType &permission) { - if(permission < 0 || permission >= PermissionType::permission_id_max) - return v2::empty_permission_values; + if(permission < 0 || permission >= PermissionType::permission_id_max) + return v2::empty_permission_values; - const auto block = this->calculate_block(permission); - if(!this->ref_block(block)) - return v2::empty_permission_values; /* TODO: may consider to throw an exception because the existence should be checked by getting the permission flags */ + const auto block = this->calculate_block(permission); + if(!this->ref_block(block)) + return v2::empty_permission_values; /* TODO: may consider to throw an exception because the existence should be checked by getting the permission flags */ - v2::PermissionValues data{this->block_containers[block]->permissions[this->calculate_block_index(permission)].values}; - this->unref_block(block); - return data; + v2::PermissionValues data{this->block_containers[block]->permissions[this->calculate_block_index(permission)].values}; + this->unref_block(block); + return data; } const v2::PermissionFlaggedValue v2::PermissionManager::permission_value_flagged(const ts::permission::PermissionType &permission) { - if(permission < 0 || permission >= PermissionType::permission_id_max) - return v2::empty_permission_flagged_value; + if(permission < 0 || permission >= PermissionType::permission_id_max) + return v2::empty_permission_flagged_value; - const auto block = this->calculate_block(permission); - if(!this->ref_block(block)) - return v2::empty_permission_flagged_value; + const auto block = this->calculate_block(permission); + if(!this->ref_block(block)) + return v2::empty_permission_flagged_value; - auto& data = this->block_containers[block]->permissions[this->calculate_block_index(permission)]; - v2::PermissionFlaggedValue result{data.values.value, data.flags.value_set}; - this->unref_block(block); - return result; + auto& data = this->block_containers[block]->permissions[this->calculate_block_index(permission)]; + v2::PermissionFlaggedValue result{data.values.value, data.flags.value_set}; + this->unref_block(block); + return result; } const v2::PermissionFlaggedValue v2::PermissionManager::permission_granted_flagged(const ts::permission::PermissionType &permission) { - if(permission < 0 || permission >= PermissionType::permission_id_max) - return v2::empty_permission_flagged_value; + if(permission < 0 || permission >= PermissionType::permission_id_max) + return v2::empty_permission_flagged_value; - const auto block = this->calculate_block(permission); - if(!this->ref_block(block)) - return v2::empty_permission_flagged_value; + const auto block = this->calculate_block(permission); + if(!this->ref_block(block)) + return v2::empty_permission_flagged_value; - auto& data = this->block_containers[block]->permissions[this->calculate_block_index(permission)]; - v2::PermissionFlaggedValue result{data.values.grant, data.flags.grant_set}; - this->unref_block(block); - return result; + auto& data = this->block_containers[block]->permissions[this->calculate_block_index(permission)]; + v2::PermissionFlaggedValue result{data.values.grant, data.flags.grant_set}; + this->unref_block(block); + return result; } static constexpr v2::PermissionContainer empty_channel_permission = {empty_flags, v2::empty_permission_values}; const v2::PermissionContainer v2::PermissionManager::channel_permission(const PermissionType &permission, ts::ChannelId channel_id) { - if(permission < 0 || permission >= PermissionType::permission_id_max) - return empty_channel_permission; + if(permission < 0 || permission >= PermissionType::permission_id_max) + return empty_channel_permission; - shared_lock channel_perm_lock(this->channel_list_lock); - for(auto& entry : this->_channel_permissions) - if(entry->permission == permission && entry->channel_id == channel_id) - return v2::PermissionContainer{entry->flags, entry->values}; - return empty_channel_permission; + shared_lock channel_perm_lock(this->channel_list_lock); + for(auto& entry : this->_channel_permissions) + if(entry->permission == permission && entry->channel_id == channel_id) + return v2::PermissionContainer{entry->flags, entry->values}; + return empty_channel_permission; } void v2::PermissionManager::set_permission(const PermissionType &permission, const v2::PermissionValues &values, const v2::PermissionUpdateType &action_value, const v2::PermissionUpdateType &action_grant, int flag_skip, int flag_negate) { - if(permission < 0 || permission >= PermissionType::permission_id_max) - return; + if(permission < 0 || permission >= PermissionType::permission_id_max) + return; - const auto block = this->calculate_block(permission); - this->ref_allocate_block(block); + const auto block = this->calculate_block(permission); + this->ref_allocate_block(block); - auto& data = this->block_containers[block]->permissions[this->calculate_block_index(permission)]; - if(action_value == v2::PermissionUpdateType::set_value) { - data.flags.value_set = true; - data.flags.flag_value_update = true; - data.values.value = values.value; - } else if(action_value == v2::PermissionUpdateType::delete_value) { - data.flags.value_set = false; - data.flags.flag_value_update = true; - data.values.value = permNotGranted; /* required for the database else it does not "deletes" the value */ - } + auto& data = this->block_containers[block]->permissions[this->calculate_block_index(permission)]; + if(action_value == v2::PermissionUpdateType::set_value) { + data.flags.value_set = true; + data.flags.flag_value_update = true; + data.values.value = values.value; + } else if(action_value == v2::PermissionUpdateType::delete_value) { + data.flags.value_set = false; + data.flags.flag_value_update = true; + data.values.value = permNotGranted; /* required for the database else it does not "deletes" the value */ + } - if(action_grant == v2::PermissionUpdateType::set_value) { - data.flags.grant_set = true; - data.flags.flag_grant_update = true; - data.values.grant = values.grant; - } else if(action_grant == v2::PermissionUpdateType::delete_value) { - data.flags.grant_set = false; - data.flags.flag_grant_update = true; - data.values.grant = permNotGranted; /* required for the database else it does not "deletes" the value */ - } + if(action_grant == v2::PermissionUpdateType::set_value) { + data.flags.grant_set = true; + data.flags.flag_grant_update = true; + data.values.grant = values.grant; + } else if(action_grant == v2::PermissionUpdateType::delete_value) { + data.flags.grant_set = false; + data.flags.flag_grant_update = true; + data.values.grant = permNotGranted; /* required for the database else it does not "deletes" the value */ + } - if(flag_skip >= 0) { - data.flags.flag_value_update = true; - data.flags.skip = flag_skip == 1; - } + if(flag_skip >= 0) { + data.flags.flag_value_update = true; + data.flags.skip = flag_skip == 1; + } - if(flag_negate >= 0) { - data.flags.flag_value_update = true; - data.flags.negate = flag_negate == 1; - } + if(flag_negate >= 0) { + data.flags.flag_value_update = true; + data.flags.negate = flag_negate == 1; + } - this->unref_block(block); - this->trigger_db_update(); + this->unref_block(block); + this->trigger_db_update(); } void v2::PermissionManager::set_channel_permission(const PermissionType &permission, ChannelId channel_id, const v2::PermissionValues &values, const v2::PermissionUpdateType &action_value, const v2::PermissionUpdateType &action_grant, int flag_skip, int flag_negate) { - if(permission < 0 || permission >= PermissionType::permission_id_max) - return; + if(permission < 0 || permission >= PermissionType::permission_id_max) + return; - unique_lock channel_perm_lock(this->channel_list_lock); - ChannelPermissionContainer* permission_container = nullptr; - for(auto& entry : this->_channel_permissions) - if(entry->permission == permission && entry->channel_id == channel_id) { - permission_container = &*entry; - break; - } + unique_lock channel_perm_lock(this->channel_list_lock); + ChannelPermissionContainer* permission_container = nullptr; + for(auto& entry : this->_channel_permissions) + if(entry->permission == permission && entry->channel_id == channel_id) { + permission_container = &*entry; + break; + } - /* register a new permission if we have no permission already*/ - if(!permission_container || !permission_container->flags.permission_set()) { /* if the permission isn't set then we have to register it again */ - if(action_value != v2::PermissionUpdateType::set_value && action_grant == v2::PermissionUpdateType::set_value) { - return; /* we were never willing to set this permission */ - } + /* register a new permission if we have no permission already*/ + if(!permission_container || !permission_container->flags.permission_set()) { /* if the permission isn't set then we have to register it again */ + if(action_value != v2::PermissionUpdateType::set_value && action_grant == v2::PermissionUpdateType::set_value) { + return; /* we were never willing to set this permission */ + } - if(!permission_container) { - auto container = make_unique(); - container->permission = permission; - container->channel_id = channel_id; - permission_container = &*container; - this->_channel_permissions.push_back(std::move(container)); - } + if(!permission_container) { + auto container = make_unique(); + container->permission = permission; + container->channel_id = channel_id; + permission_container = &*container; + this->_channel_permissions.push_back(std::move(container)); + } - /* now set the channel flag for that permission */ - const auto block = this->calculate_block(permission); - this->ref_allocate_block(block); + /* now set the channel flag for that permission */ + const auto block = this->calculate_block(permission); + this->ref_allocate_block(block); - auto& data = this->block_containers[block]->permissions[this->calculate_block_index(permission)]; - data.flags.channel_specific = true; - this->unref_block(block); - } + auto& data = this->block_containers[block]->permissions[this->calculate_block_index(permission)]; + data.flags.channel_specific = true; + this->unref_block(block); + } - if(action_value == v2::PermissionUpdateType::set_value) { - permission_container->flags.value_set = true; - permission_container->flags.flag_value_update = true; - permission_container->values.value = values.value; - } else if(action_value == v2::PermissionUpdateType::delete_value) { - permission_container->flags.value_set = false; - permission_container->flags.flag_value_update = true; - } + if(action_value == v2::PermissionUpdateType::set_value) { + permission_container->flags.value_set = true; + permission_container->flags.flag_value_update = true; + permission_container->values.value = values.value; + } else if(action_value == v2::PermissionUpdateType::delete_value) { + permission_container->flags.value_set = false; + permission_container->flags.flag_value_update = true; + } - if(action_grant == v2::PermissionUpdateType::set_value) { - permission_container->flags.grant_set = true; - permission_container->flags.flag_grant_update = true; - permission_container->values.grant = values.grant; - } else if(action_grant == v2::PermissionUpdateType::delete_value) { - permission_container->flags.grant_set = false; - permission_container->flags.flag_grant_update = true; - } + if(action_grant == v2::PermissionUpdateType::set_value) { + permission_container->flags.grant_set = true; + permission_container->flags.flag_grant_update = true; + permission_container->values.grant = values.grant; + } else if(action_grant == v2::PermissionUpdateType::delete_value) { + permission_container->flags.grant_set = false; + permission_container->flags.flag_grant_update = true; + } - if(flag_skip >= 0) { - permission_container->flags.flag_value_update = true; - permission_container->flags.skip = flag_skip == 1; - } + if(flag_skip >= 0) { + permission_container->flags.flag_value_update = true; + permission_container->flags.skip = flag_skip == 1; + } - if(flag_negate >= 0) { - permission_container->flags.flag_value_update = true; - permission_container->flags.negate = flag_negate == 1; - } + if(flag_negate >= 0) { + permission_container->flags.flag_value_update = true; + permission_container->flags.negate = flag_negate == 1; + } - if(!permission_container->flags.permission_set()) { /* unregister the permission again because its unset, we delete the channel permission as soon we've flushed the updates */ - auto other_channel_permission = std::find_if(this->_channel_permissions.begin(), this->_channel_permissions.end(), [&](unique_ptr& perm) { return perm->permission == permission && perm->flags.permission_set(); }); - if(other_channel_permission == this->_channel_permissions.end()) { /* no more channel specific permissions c*/ - const auto block = this->calculate_block(permission); - if(this->ref_block(block)) { - this->block_containers[block]->permissions[this->calculate_block_index(permission)].flags.channel_specific = false; - this->unref_block(block); - } - } - } - this->trigger_db_update(); + if(!permission_container->flags.permission_set()) { /* unregister the permission again because its unset, we delete the channel permission as soon we've flushed the updates */ + auto other_channel_permission = std::find_if(this->_channel_permissions.begin(), this->_channel_permissions.end(), [&](unique_ptr& perm) { return perm->permission == permission && perm->flags.permission_set(); }); + if(other_channel_permission == this->_channel_permissions.end()) { /* no more channel specific permissions c*/ + const auto block = this->calculate_block(permission); + if(this->ref_block(block)) { + this->block_containers[block]->permissions[this->calculate_block_index(permission)].flags.channel_specific = false; + this->unref_block(block); + } + } + } + this->trigger_db_update(); } const std::vector> v2::PermissionManager::permissions() { - std::unique_lock use_lock(this->block_use_count_lock); - decltype(this->block_containers) block_containers; /* save the states/nullptr's */ - memcpy(block_containers, this->block_containers, sizeof(this->block_containers)); - size_t block_count = 0; - for(size_t index = 0; index < BULK_COUNT; index++) { - if(block_containers[index]) { - block_count++; - this->block_use_count[index]++; - } - } - use_lock.unlock(); + std::unique_lock use_lock(this->block_use_count_lock); + decltype(this->block_containers) block_containers; /* save the states/nullptr's */ + memcpy(block_containers, this->block_containers, sizeof(this->block_containers)); + size_t block_count = 0; + for(size_t index = 0; index < BULK_COUNT; index++) { + if(block_containers[index]) { + block_count++; + this->block_use_count[index]++; + } + } + use_lock.unlock(); - vector> result; - result.reserve(block_count * PERMISSIONS_BULK_ENTRY_COUNT); + vector> result; + result.reserve(block_count * PERMISSIONS_BULK_ENTRY_COUNT); - for(size_t block_index = 0; block_index < BULK_COUNT; block_index++) { - auto& block = block_containers[block_index]; - if(!block) - continue; + for(size_t block_index = 0; block_index < BULK_COUNT; block_index++) { + auto& block = block_containers[block_index]; + if(!block) + continue; - for(size_t permission_index = 0; permission_index < PERMISSIONS_BULK_ENTRY_COUNT; permission_index++) { - auto& permission = block->permissions[permission_index]; - if(!permission.flags.permission_set()) - continue; + for(size_t permission_index = 0; permission_index < PERMISSIONS_BULK_ENTRY_COUNT; permission_index++) { + auto& permission = block->permissions[permission_index]; + if(!permission.flags.permission_set()) + continue; - result.emplace_back((PermissionType) (block_index * PERMISSIONS_BULK_ENTRY_COUNT + permission_index), permission); - } - } - result.shrink_to_fit(); + result.emplace_back((PermissionType) (block_index * PERMISSIONS_BULK_ENTRY_COUNT + permission_index), permission); + } + } + result.shrink_to_fit(); - use_lock.lock(); - for(size_t index = 0; index < BULK_COUNT; index++) { - if(block_containers[index]) - this->block_use_count[index]--; - } - use_lock.unlock(); + use_lock.lock(); + for(size_t index = 0; index < BULK_COUNT; index++) { + if(block_containers[index]) + this->block_use_count[index]--; + } + use_lock.unlock(); - return result; + return result; } const vector> v2::PermissionManager::channel_permissions(ts::ChannelId channel_id) { - shared_lock channel_perm_lock(this->channel_list_lock); + shared_lock channel_perm_lock(this->channel_list_lock); - vector> result; - for(auto& entry : this->_channel_permissions) - if((channel_id == entry->channel_id) && (entry->flags.value_set || entry->flags.grant_set)) - result.emplace_back(entry->permission, v2::PermissionContainer{entry->flags, entry->values}); - return result; + vector> result; + for(auto& entry : this->_channel_permissions) + if((channel_id == entry->channel_id) && (entry->flags.value_set || entry->flags.grant_set)) + result.emplace_back(entry->permission, v2::PermissionContainer{entry->flags, entry->values}); + return result; } const vector> v2::PermissionManager::channel_permissions() { - shared_lock channel_perm_lock(this->channel_list_lock); + shared_lock channel_perm_lock(this->channel_list_lock); - vector> result; - for(auto& entry : this->_channel_permissions) - if(entry->flags.value_set || entry->flags.grant_set) - result.emplace_back(entry->permission, entry->channel_id, v2::PermissionContainer{entry->flags, entry->values}); - return result; + vector> result; + for(auto& entry : this->_channel_permissions) + if(entry->flags.value_set || entry->flags.grant_set) + result.emplace_back(entry->permission, entry->channel_id, v2::PermissionContainer{entry->flags, entry->values}); + return result; } const std::vector v2::PermissionManager::flush_db_updates() { - if(!this->requires_db_save) - return {}; + if(!this->requires_db_save) + return {}; - this->requires_db_save = false; - std::vector result; + this->requires_db_save = false; + std::vector result; - { - lock_guard use_lock(this->block_use_count_lock); - size_t block_count = 0; - for (auto &block_container : block_containers) - if (block_container) - block_count++; - result.reserve(block_count * PERMISSIONS_BULK_ENTRY_COUNT); + { + lock_guard use_lock(this->block_use_count_lock); + size_t block_count = 0; + for (auto &block_container : block_containers) + if (block_container) + block_count++; + result.reserve(block_count * PERMISSIONS_BULK_ENTRY_COUNT); - for(size_t block_index = 0; block_index < BULK_COUNT; block_index++) { - auto& block = block_containers[block_index]; - if(!block) - continue; + for(size_t block_index = 0; block_index < BULK_COUNT; block_index++) { + auto& block = block_containers[block_index]; + if(!block) + continue; - for(size_t permission_index = 0; permission_index < PERMISSIONS_BULK_ENTRY_COUNT; permission_index++) { - auto& permission = block->permissions[permission_index]; + for(size_t permission_index = 0; permission_index < PERMISSIONS_BULK_ENTRY_COUNT; permission_index++) { + auto& permission = block->permissions[permission_index]; - if(!permission.flags.flag_value_update && !permission.flags.flag_grant_update) - continue; + if(!permission.flags.flag_value_update && !permission.flags.flag_grant_update) + continue; - /* we only need an update it the permission has a DB reference or we will set the permission */ - if(permission.flags.database_reference || permission.flags.permission_set()) { - /* - PermissionType permission; - ChannelId channel_id; + /* we only need an update it the permission has a DB reference or we will set the permission */ + if(permission.flags.database_reference || permission.flags.permission_set()) { + /* + PermissionType permission; + ChannelId channel_id; - PermissionValues values; - PermissionUpdateType update_value; - PermissionUpdateType update_grant; + PermissionValues values; + PermissionUpdateType update_value; + PermissionUpdateType update_grant; - bool flag_db: 1; - bool flag_delete: 1; - bool flag_skip: 1; - bool flag_negate: 1; - */ - auto& entry = result.emplace_back(v2::PermissionDBUpdateEntry{ - (PermissionType) (block_index * PERMISSIONS_BULK_ENTRY_COUNT + permission_index), - (ChannelId) 0, + bool flag_db: 1; + bool flag_delete: 1; + bool flag_skip: 1; + bool flag_negate: 1; + */ + auto& entry = result.emplace_back(v2::PermissionDBUpdateEntry{ + (PermissionType) (block_index * PERMISSIONS_BULK_ENTRY_COUNT + permission_index), + (ChannelId) 0, - permission.values, - (PermissionUpdateType) (permission.flags.flag_value_update ? (permission.flags.value_set ? PermissionUpdateType::set_value : PermissionUpdateType::delete_value) : PermissionUpdateType::do_nothing), - (PermissionUpdateType) (permission.flags.flag_grant_update ? (permission.flags.grant_set ? PermissionUpdateType::set_value : PermissionUpdateType::delete_value) : PermissionUpdateType::do_nothing), + permission.values, + (PermissionUpdateType) (permission.flags.flag_value_update ? (permission.flags.value_set ? PermissionUpdateType::set_value : PermissionUpdateType::delete_value) : PermissionUpdateType::do_nothing), + (PermissionUpdateType) (permission.flags.flag_grant_update ? (permission.flags.grant_set ? PermissionUpdateType::set_value : PermissionUpdateType::delete_value) : PermissionUpdateType::do_nothing), - (bool) permission.flags.database_reference, - (bool) !permission.flags.permission_set(), /* db delete */ - (bool) permission.flags.skip, - (bool) permission.flags.negate - }); + (bool) permission.flags.database_reference, + (bool) !permission.flags.permission_set(), /* db delete */ + (bool) permission.flags.skip, + (bool) permission.flags.negate + }); - /* required for the database */ - if(!permission.flags.value_set) - entry.values.value = permNotGranted; + /* required for the database */ + if(!permission.flags.value_set) + entry.values.value = permNotGranted; - if(!permission.flags.grant_set) - entry.values.grant = permNotGranted; + if(!permission.flags.grant_set) + entry.values.grant = permNotGranted; - permission.flags.database_reference = permission.flags.permission_set(); - } + permission.flags.database_reference = permission.flags.permission_set(); + } - permission.flags.flag_value_update = false; - permission.flags.flag_grant_update = false; - } - } - } - { - lock_guard chanel_lock(this->channel_list_lock); - for(size_t index = 0; index < this->_channel_permissions.size(); index++) { - auto& permission = this->_channel_permissions[index]; - if(!permission->flags.flag_value_update && !permission->flags.flag_grant_update) - continue; + permission.flags.flag_value_update = false; + permission.flags.flag_grant_update = false; + } + } + } + { + lock_guard chanel_lock(this->channel_list_lock); + for(size_t index = 0; index < this->_channel_permissions.size(); index++) { + auto& permission = this->_channel_permissions[index]; + if(!permission->flags.flag_value_update && !permission->flags.flag_grant_update) + continue; - /* we only need an update it the permission has a DB reference or we will set the permission */ - if(permission->flags.database_reference || permission->flags.permission_set()) { + /* we only need an update it the permission has a DB reference or we will set the permission */ + if(permission->flags.database_reference || permission->flags.permission_set()) { - auto& entry = result.emplace_back(v2::PermissionDBUpdateEntry{ - permission->permission, - permission->channel_id, + auto& entry = result.emplace_back(v2::PermissionDBUpdateEntry{ + permission->permission, + permission->channel_id, - permission->values, - (PermissionUpdateType) (permission->flags.flag_value_update ? (permission->flags.value_set ? PermissionUpdateType::set_value : PermissionUpdateType::delete_value) : PermissionUpdateType::do_nothing), - (PermissionUpdateType) (permission->flags.flag_grant_update ? (permission->flags.grant_set ? PermissionUpdateType::set_value : PermissionUpdateType::delete_value) : PermissionUpdateType::do_nothing), + permission->values, + (PermissionUpdateType) (permission->flags.flag_value_update ? (permission->flags.value_set ? PermissionUpdateType::set_value : PermissionUpdateType::delete_value) : PermissionUpdateType::do_nothing), + (PermissionUpdateType) (permission->flags.flag_grant_update ? (permission->flags.grant_set ? PermissionUpdateType::set_value : PermissionUpdateType::delete_value) : PermissionUpdateType::do_nothing), - (bool) permission->flags.database_reference, - (bool) !permission->flags.permission_set(), /* db delete */ - (bool) permission->flags.skip, - (bool) permission->flags.negate - }); + (bool) permission->flags.database_reference, + (bool) !permission->flags.permission_set(), /* db delete */ + (bool) permission->flags.skip, + (bool) permission->flags.negate + }); - /* required for the database */ - if(!permission->flags.value_set) - entry.values.value = permNotGranted; + /* required for the database */ + if(!permission->flags.value_set) + entry.values.value = permNotGranted; - if(!permission->flags.grant_set) - entry.values.grant = permNotGranted; + if(!permission->flags.grant_set) + entry.values.grant = permNotGranted; - permission->flags.database_reference = permission->flags.permission_set(); - } + permission->flags.database_reference = permission->flags.permission_set(); + } - permission->flags.flag_value_update = false; - permission->flags.flag_grant_update = false; - if(!permission->flags.permission_set()) { - this->_channel_permissions.erase(this->_channel_permissions.begin() + index); - index--; - } - } - } + permission->flags.flag_value_update = false; + permission->flags.flag_grant_update = false; + if(!permission->flags.permission_set()) { + this->_channel_permissions.erase(this->_channel_permissions.begin() + index); + index--; + } + } + } - return result; + return result; } size_t v2::PermissionManager::used_memory() { - size_t result = sizeof(*this); + size_t result = sizeof(*this); - for (auto &block_container : block_containers) { - if (block_container) - result += sizeof(PermissionContainerBulk); - } + for (auto &block_container : block_containers) { + if (block_container) + result += sizeof(PermissionContainerBulk); + } - { + { - shared_lock channel_lock(this->channel_list_lock); - result += this->_channel_permissions.size() * (sizeof(ChannelPermissionContainer) + sizeof(unique_ptr)); - } + shared_lock channel_lock(this->channel_list_lock); + result += this->_channel_permissions.size() * (sizeof(ChannelPermissionContainer) + sizeof(unique_ptr)); + } - return result; + return result; } void v2::PermissionManager::cleanup() { - lock_guard use_lock(this->block_use_count_lock); + lock_guard use_lock(this->block_use_count_lock); - for (auto &block_container : block_containers) { - if (!block_container) continue; + for (auto &block_container : block_containers) { + if (!block_container) continue; - bool used = false; - for(auto& permission : block_container->permissions) { - if(permission.flags.value_set || permission.flags.grant_set || permission.flags.channel_specific) { - used = true; - break; - } - } - if(used) - continue; + bool used = false; + for(auto& permission : block_container->permissions) { + if(permission.flags.value_set || permission.flags.grant_set || permission.flags.channel_specific) { + used = true; + break; + } + } + if(used) + continue; - delete block_container; - block_container = nullptr; - } + delete block_container; + block_container = nullptr; + } } diff --git a/src/PermissionManager.h b/src/PermissionManager.h index 8185f75..68c59d4 100644 --- a/src/PermissionManager.h +++ b/src/PermissionManager.h @@ -33,13 +33,13 @@ namespace ts { enum PermissionType : uint16_t { undefined = (uint16_t) -1, - permission_id_min = 0, /* we count unknown as defined permission as well */ + permission_id_min = 0, /* we count unknown as defined permission as well */ unknown = (uint16_t) 0, type_begin = 1, /* global */ - /* global::information */ + /* global::information */ b_serverinstance_help_view = type_begin, b_serverinstance_version_view, b_serverinstance_info_view, @@ -49,7 +49,7 @@ namespace ts { b_serverinstance_permission_find, //b_serverinstance_allow_teaspeak_plugin, - /* global::vs_management */ + /* global::vs_management */ b_virtualserver_create, b_virtualserver_delete, b_virtualserver_start_any, @@ -57,23 +57,23 @@ namespace ts { b_virtualserver_change_machine_id, b_virtualserver_change_template, - /* global::administration */ + /* global::administration */ b_serverquery_login, b_serverinstance_textmessage_send, b_serverinstance_log_view, b_serverinstance_log_add, b_serverinstance_stop, - /* global::settings */ + /* global::settings */ b_serverinstance_modify_settings, b_serverinstance_modify_querygroup, b_serverinstance_modify_templates, - /* virtual_server */ + /* virtual_server */ - /* virtual_server::information */ + /* virtual_server::information */ b_virtualserver_select, - b_virtualserver_select_godmode, + b_virtualserver_select_godmode, b_virtualserver_info_view, b_virtualserver_connectioninfo_view, b_virtualserver_channel_list, @@ -86,7 +86,7 @@ namespace ts { b_virtualserver_permission_find, b_virtualserver_custom_search, - /* virtual_server::administration */ + /* virtual_server::administration */ b_virtualserver_start, b_virtualserver_stop, b_virtualserver_token_list, @@ -102,14 +102,14 @@ namespace ts { b_virtualserver_snapshot_deploy, b_virtualserver_permission_reset, - /* virtual_server::settings */ + /* virtual_server::settings */ b_virtualserver_modify_name, b_virtualserver_modify_welcomemessage, b_virtualserver_modify_maxclients, b_virtualserver_modify_reserved_slots, b_virtualserver_modify_password, b_virtualserver_modify_default_servergroup, - b_virtualserver_modify_default_musicgroup, + b_virtualserver_modify_default_musicgroup, b_virtualserver_modify_default_channelgroup, b_virtualserver_modify_default_channeladmingroup, b_virtualserver_modify_channel_forced_silence, @@ -123,7 +123,7 @@ namespace ts { b_virtualserver_modify_port, #ifndef LAGENCY b_virtualserver_modify_host, - b_virtualserver_modify_default_messages, + b_virtualserver_modify_default_messages, #endif b_virtualserver_modify_autostart, b_virtualserver_modify_needed_identity_security_level, @@ -132,25 +132,25 @@ namespace ts { b_virtualserver_modify_min_client_version, b_virtualserver_modify_icon_id, b_virtualserver_modify_weblist, - b_virtualserver_modify_country_code, + b_virtualserver_modify_country_code, b_virtualserver_modify_codec_encryption_mode, b_virtualserver_modify_temporary_passwords, b_virtualserver_modify_temporary_passwords_own, b_virtualserver_modify_channel_temp_delete_delay_default, b_virtualserver_modify_music_bot_limit, - /* channel */ + /* channel */ i_channel_min_depth, i_channel_max_depth, b_channel_group_inheritance_end, i_channel_permission_modify_power, i_channel_needed_permission_modify_power, - /* channel::info */ + /* channel::info */ b_channel_info_view, - b_virtualserver_channel_permission_list, + b_virtualserver_channel_permission_list, - /* channel::create */ + /* channel::create */ b_channel_create_child, b_channel_create_permanent, b_channel_create_semi_permanent, @@ -171,14 +171,14 @@ namespace ts { b_channel_create_with_maxfamilyclients, b_channel_create_with_sortorder, b_channel_create_with_default, - b_channel_create_with_needed_talk_power, + b_channel_create_with_needed_talk_power, b_channel_create_modify_with_force_password, i_channel_create_modify_with_temp_delete_delay, - i_channel_create_modify_conversation_history_length, - b_channel_create_modify_conversation_history_unlimited, - b_channel_create_modify_conversation_private, + i_channel_create_modify_conversation_history_length, + b_channel_create_modify_conversation_history_unlimited, + b_channel_create_modify_conversation_private, - /* channel::modify */ + /* channel::modify */ b_channel_modify_parent, b_channel_modify_make_default, b_channel_modify_make_permanent, @@ -201,7 +201,7 @@ namespace ts { b_channel_modify_temp_delete_delay, b_channel_conversation_message_delete, - /* channel::delete */ + /* channel::delete */ b_channel_delete_permanent, b_channel_delete_semi_permanent, b_channel_delete_temporary, @@ -209,7 +209,7 @@ namespace ts { i_channel_delete_power, i_channel_needed_delete_power, - /* channel::access */ + /* channel::access */ b_channel_join_permanent, b_channel_join_semi_permanent, b_channel_join_temporary, @@ -217,25 +217,25 @@ namespace ts { b_channel_join_ignore_maxclients, i_channel_join_power, i_channel_needed_join_power, - b_channel_ignore_join_power, + b_channel_ignore_join_power, - i_channel_view_power, - i_channel_needed_view_power, - b_channel_ignore_view_power, + i_channel_view_power, + i_channel_needed_view_power, + b_channel_ignore_view_power, i_channel_subscribe_power, i_channel_needed_subscribe_power, - b_channel_ignore_subscribe_power, + b_channel_ignore_subscribe_power, i_channel_description_view_power, i_channel_needed_description_view_power, - b_channel_ignore_description_view_power, + b_channel_ignore_description_view_power, - /* group */ + /* group */ i_icon_id, i_max_icon_filesize, - i_max_playlist_size, - i_max_playlists, + i_max_playlist_size, + i_max_playlists, b_icon_manage, b_group_is_permanent, i_group_auto_update_type, @@ -243,20 +243,20 @@ namespace ts { i_group_sort_id, i_group_show_name_in_tree, - /* group::info */ - b_virtualserver_servergroup_list, //Unused - b_virtualserver_servergroup_permission_list, - b_virtualserver_servergroup_client_list, + /* group::info */ + b_virtualserver_servergroup_list, //Unused + b_virtualserver_servergroup_permission_list, + b_virtualserver_servergroup_client_list, - b_virtualserver_channelgroup_list, //Unused - b_virtualserver_channelgroup_permission_list, - b_virtualserver_channelgroup_client_list, + b_virtualserver_channelgroup_list, //Unused + b_virtualserver_channelgroup_permission_list, + b_virtualserver_channelgroup_client_list, - /* group::create */ - b_virtualserver_servergroup_create, - b_virtualserver_channelgroup_create, + /* group::create */ + b_virtualserver_servergroup_create, + b_virtualserver_channelgroup_create, - /* group::modify */ + /* group::modify */ #ifdef LAGENCY i_group_modify_power, i_group_needed_modify_power, @@ -269,18 +269,18 @@ namespace ts { i_server_group_modify_power, i_server_group_needed_modify_power, i_server_group_member_add_power, - i_server_group_self_add_power, + i_server_group_self_add_power, i_server_group_needed_member_add_power, i_server_group_member_remove_power, - i_server_group_self_remove_power, + i_server_group_self_remove_power, i_server_group_needed_member_remove_power, i_channel_group_modify_power, i_channel_group_needed_modify_power, i_channel_group_member_add_power, - i_channel_group_self_add_power, + i_channel_group_self_add_power, i_channel_group_needed_member_add_power, i_channel_group_member_remove_power, - i_channel_group_self_remove_power, + i_channel_group_self_remove_power, i_channel_group_needed_member_remove_power, i_displayed_group_member_add_power, @@ -294,11 +294,11 @@ namespace ts { i_permission_modify_power, b_permission_modify_power_ignore, - /* group::delete */ + /* group::delete */ b_virtualserver_servergroup_delete, b_virtualserver_channelgroup_delete, - /* client */ + /* client */ i_client_permission_modify_power, i_client_needed_permission_modify_power, i_client_max_clones_uid, @@ -307,18 +307,18 @@ namespace ts { i_client_max_idletime, i_client_max_avatar_filesize, i_client_max_channel_subscriptions, - i_client_max_channels, - i_client_max_temporary_channels, - i_client_max_semi_channels, - i_client_max_permanent_channels, + i_client_max_channels, + i_client_max_temporary_channels, + i_client_max_semi_channels, + i_client_max_permanent_channels, b_client_use_priority_speaker, - b_client_is_priority_speaker, + b_client_is_priority_speaker, b_client_skip_channelgroup_permissions, b_client_force_push_to_talk, b_client_ignore_bans, - b_client_ignore_vpn, + b_client_ignore_vpn, b_client_ignore_antiflood, - b_client_enforce_valid_hwid, + b_client_enforce_valid_hwid, b_client_allow_invalid_packet, b_client_allow_invalid_badges, b_client_issue_client_query_command, @@ -329,43 +329,43 @@ namespace ts { b_client_is_sticky, b_client_ignore_sticky, - b_client_music_create_permanent, - b_client_music_create_semi_permanent, - b_client_music_create_temporary, - b_client_music_modify_permanent, - b_client_music_modify_semi_permanent, - b_client_music_modify_temporary, - i_client_music_create_modify_max_volume, + b_client_music_create_permanent, + b_client_music_create_semi_permanent, + b_client_music_create_temporary, + b_client_music_modify_permanent, + b_client_music_modify_semi_permanent, + b_client_music_modify_temporary, + i_client_music_create_modify_max_volume, i_client_music_limit, i_client_music_needed_delete_power, i_client_music_delete_power, i_client_music_play_power, i_client_music_needed_play_power, - i_client_music_modify_power, - i_client_music_needed_modify_power, + i_client_music_modify_power, + i_client_music_needed_modify_power, i_client_music_rename_power, i_client_music_needed_rename_power, - b_virtualserver_playlist_permission_list, + b_virtualserver_playlist_permission_list, b_playlist_create, i_playlist_view_power, - i_playlist_needed_view_power, - i_playlist_modify_power, - i_playlist_needed_modify_power, - i_playlist_permission_modify_power, - i_playlist_needed_permission_modify_power, - i_playlist_delete_power, - i_playlist_needed_delete_power, + i_playlist_needed_view_power, + i_playlist_modify_power, + i_playlist_needed_modify_power, + i_playlist_permission_modify_power, + i_playlist_needed_permission_modify_power, + i_playlist_delete_power, + i_playlist_needed_delete_power, - i_playlist_song_add_power, - i_playlist_song_needed_add_power, - i_playlist_song_remove_power, - i_playlist_song_needed_remove_power, - i_playlist_song_move_power, - i_playlist_song_needed_move_power, + i_playlist_song_add_power, + i_playlist_song_needed_add_power, + i_playlist_song_remove_power, + i_playlist_song_needed_remove_power, + i_playlist_song_move_power, + i_playlist_song_needed_move_power, - /* client::info */ + /* client::info */ b_client_info_view, b_client_permissionoverview_view, b_client_permissionoverview_own, @@ -377,10 +377,10 @@ namespace ts { b_client_music_server_list, i_client_music_info, i_client_music_needed_info, - b_virtualserver_channelclient_permission_list, - b_virtualserver_client_permission_list, + b_virtualserver_channelclient_permission_list, + b_virtualserver_client_permission_list, - /* client::admin */ + /* client::admin */ i_client_kick_from_server_power, i_client_needed_kick_from_server_power, i_client_kick_from_channel_power, @@ -391,26 +391,26 @@ namespace ts { i_client_needed_move_power, i_client_complain_power, i_client_needed_complain_power, - b_client_complain_list, - b_client_complain_delete_own, - b_client_complain_delete, - b_client_ban_list, - b_client_ban_list_global, - b_client_ban_trigger_list, - b_client_ban_create, - b_client_ban_create_global, - b_client_ban_name, - b_client_ban_ip, - b_client_ban_hwid, - b_client_ban_edit, - b_client_ban_edit_global, - b_client_ban_delete_own, - b_client_ban_delete, - b_client_ban_delete_own_global, - b_client_ban_delete_global, - i_client_ban_max_bantime, + b_client_complain_list, + b_client_complain_delete_own, + b_client_complain_delete, + b_client_ban_list, + b_client_ban_list_global, + b_client_ban_trigger_list, + b_client_ban_create, + b_client_ban_create_global, + b_client_ban_name, + b_client_ban_ip, + b_client_ban_hwid, + b_client_ban_edit, + b_client_ban_edit_global, + b_client_ban_delete_own, + b_client_ban_delete, + b_client_ban_delete_own_global, + b_client_ban_delete_global, + i_client_ban_max_bantime, - /* client::basics */ + /* client::basics */ i_client_private_textmessage_power, i_client_needed_private_textmessage_power, b_client_even_textmessage_send, @@ -425,27 +425,27 @@ namespace ts { i_client_whisper_power, i_client_needed_whisper_power, - /* client::modify */ + /* client::modify */ b_client_modify_description, b_client_modify_own_description, - b_client_use_bbcode_any, - b_client_use_bbcode_url, - b_client_use_bbcode_image, + b_client_use_bbcode_any, + b_client_use_bbcode_url, + b_client_use_bbcode_image, b_client_modify_dbproperties, b_client_delete_dbproperties, b_client_create_modify_serverquery_login, b_client_query_create, - b_client_query_list, - b_client_query_list_own, - b_client_query_rename, - b_client_query_rename_own, - b_client_query_change_password, - b_client_query_change_own_password, - b_client_query_change_password_global, - b_client_query_delete, - b_client_query_delete_own, + b_client_query_list, + b_client_query_list_own, + b_client_query_rename, + b_client_query_rename_own, + b_client_query_change_password, + b_client_query_change_own_password, + b_client_query_change_password_global, + b_client_query_delete, + b_client_query_delete_own, - /* file_transfer */ + /* file_transfer */ b_ft_ignore_password, b_ft_transfer_list, i_ft_file_upload_power, @@ -465,7 +465,7 @@ namespace ts { permission_id_max }; - inline PermissionType& operator&=(PermissionType& a, int b) { return a = (PermissionType) ((int) a & b); } + inline PermissionType& operator&=(PermissionType& a, int b) { return a = (PermissionType) ((int) a & b); } enum PermissionGroup : uint16_t { group_begin, @@ -519,27 +519,27 @@ namespace ts { }; struct PermissionTypeEntry { - static std::shared_ptr unknown; + static std::shared_ptr unknown; - PermissionTypeEntry& operator=(const PermissionTypeEntry& other) = delete; - /* - PermissionTypeEntry& operator=(const PermissionTypeEntry& other) { - this->type = other.type; - this->group = other.group; - this->name = other.name; - this->description = other.description; - this->clientSupported = other.clientSupported; + PermissionTypeEntry& operator=(const PermissionTypeEntry& other) = delete; + /* + PermissionTypeEntry& operator=(const PermissionTypeEntry& other) { + this->type = other.type; + this->group = other.group; + this->name = other.name; + this->description = other.description; + this->clientSupported = other.clientSupported; - this->grant_name = std::string() + (name[0] == 'i' ? "i" : "i") + "_needed_modify_power_" + name.substr(2); - return *this; - } + this->grant_name = std::string() + (name[0] == 'i' ? "i" : "i") + "_needed_modify_power_" + name.substr(2); + return *this; + } - bool operator==(const PermissionTypeEntry& other) { - return other.type == this->type; - } - */ + bool operator==(const PermissionTypeEntry& other) { + return other.type == this->type; + } + */ - PermissionType type; + PermissionType type; PermissionGroup group; std::string name; std::string grant_name; @@ -548,72 +548,72 @@ namespace ts { bool clientSupported = true; - // PermissionTypeEntry(PermissionTypeEntry&& ref) : type(ref.type), group(ref.group), name(ref.name), description(ref.description), clientSupported(ref.clientSupported) {} - //PermissionTypeEntry(const PermissionTypeEntry& ref) : type(ref.type), group(ref.group), name(ref.name), description(ref.description), clientSupported(ref.clientSupported) {} - PermissionTypeEntry(PermissionTypeEntry&& ref) = delete; - PermissionTypeEntry(const PermissionTypeEntry& ref) = delete; - //PermissionTypeEntry(const PermissionTypeEntry& ref) : type(ref.type), group(ref.group), name(ref.name), description(ref.description), clientSupported(ref.clientSupported) {} + // PermissionTypeEntry(PermissionTypeEntry&& ref) : type(ref.type), group(ref.group), name(ref.name), description(ref.description), clientSupported(ref.clientSupported) {} + //PermissionTypeEntry(const PermissionTypeEntry& ref) : type(ref.type), group(ref.group), name(ref.name), description(ref.description), clientSupported(ref.clientSupported) {} + PermissionTypeEntry(PermissionTypeEntry&& ref) = delete; + PermissionTypeEntry(const PermissionTypeEntry& ref) = delete; + //PermissionTypeEntry(const PermissionTypeEntry& ref) : type(ref.type), group(ref.group), name(ref.name), description(ref.description), clientSupported(ref.clientSupported) {} - PermissionTypeEntry(PermissionType type, PermissionGroup group, std::string name, std::string description, bool clientSupported = true) : type(type), - group(group), - name(std::move(name)), - description(std::move(description)), - clientSupported(clientSupported) { - this->grant_name = std::string() + (this->name[0] == 'i' ? "i" : "i") + "_needed_modify_power_" + this->name.substr(2); - } + PermissionTypeEntry(PermissionType type, PermissionGroup group, std::string name, std::string description, bool clientSupported = true) : type(type), + group(group), + name(std::move(name)), + description(std::move(description)), + clientSupported(clientSupported) { + this->grant_name = std::string() + (this->name[0] == 'i' ? "i" : "i") + "_needed_modify_power_" + this->name.substr(2); + } }; - namespace teamspeak { - enum GroupType { - GENERAL, - SERVER, - CHANNEL, - CLIENT - }; + namespace teamspeak { + enum GroupType { + GENERAL, + SERVER, + CHANNEL, + CLIENT + }; - typedef std::map>> MapType; - extern MapType unmapping; - extern MapType mapping; - extern std::deque map_key(std::string key, GroupType type); //TeamSpeak -> TeaSpeak - extern std::deque unmap_key(std::string key, GroupType type); //TeaSpeak -> TeamSpeak - } + typedef std::map>> MapType; + extern MapType unmapping; + extern MapType mapping; + extern std::deque map_key(std::string key, GroupType type); //TeamSpeak -> TeaSpeak + extern std::deque unmap_key(std::string key, GroupType type); //TeaSpeak -> TeamSpeak + } - namespace update { - enum GroupUpdateType { - NONE = 0, + namespace update { + enum GroupUpdateType { + NONE = 0, - CHANNEL_GUEST = 10, - CHANNEL_VOICE = 25, - CHANNEL_OPERATOR = 35, - CHANNEL_ADMIN = 40, + CHANNEL_GUEST = 10, + CHANNEL_VOICE = 25, + CHANNEL_OPERATOR = 35, + CHANNEL_ADMIN = 40, - SERVER_GUEST = 15, - SERVER_NORMAL = 30, - SERVER_ADMIN = 45, + SERVER_GUEST = 15, + SERVER_NORMAL = 30, + SERVER_ADMIN = 45, - QUERY_GUEST = 20, - QUERY_ADMIN = 50 - }; + QUERY_GUEST = 20, + QUERY_ADMIN = 50 + }; - struct UpdatePermission { - UpdatePermission(std::string name, permission::PermissionValue value, permission::PermissionValue granted, bool negated, bool skipped) : name(std::move(name)), value(value), granted(granted), negated(negated), skipped(skipped) {} - UpdatePermission() = default; + struct UpdatePermission { + UpdatePermission(std::string name, permission::PermissionValue value, permission::PermissionValue granted, bool negated, bool skipped) : name(std::move(name)), value(value), granted(granted), negated(negated), skipped(skipped) {} + UpdatePermission() = default; - std::string name; - permission::PermissionValue value = permNotGranted; - permission::PermissionValue granted = permNotGranted; + std::string name; + permission::PermissionValue value = permNotGranted; + permission::PermissionValue granted = permNotGranted; - bool negated = false; - bool skipped = false; - }; + bool negated = false; + bool skipped = false; + }; - struct UpdateEntry { - GroupUpdateType type; - UpdatePermission permission; - }; + struct UpdateEntry { + GroupUpdateType type; + UpdatePermission permission; + }; - extern std::deque migrate; //TeamSpeak -> TeaSpeak - } + extern std::deque migrate; //TeamSpeak -> TeaSpeak + } extern std::deque> availablePermissions; extern std::deque neededPermissions; @@ -621,7 +621,7 @@ namespace ts { void setup_permission_resolve(); std::shared_ptr resolvePermissionData(PermissionType); - std::shared_ptr resolvePermissionData(const std::string&); + std::shared_ptr resolvePermissionData(const std::string&); #define PERM_FLAG_PRIVATE 0b1 #define PERM_FLAG_PUBLIC 0b10 @@ -647,7 +647,7 @@ namespace ts { bool hasValue(){ return value != permNotGranted; } bool hasGrant(){ return granted != permNotGranted; } - std::shared_ptr type; + std::shared_ptr type; PermissionValue value; PermissionValue granted; uint16_t flagMask; @@ -663,12 +663,12 @@ namespace ts { ~PermissionManager(); std::shared_ptr registerPermission(PermissionType, PermissionValue, const std::shared_ptr& channel, uint16_t = PERM_FLAG_PUBLIC); - std::shared_ptr registerPermission(const std::shared_ptr&, PermissionValue, const std::shared_ptr& channel, uint16_t = PERM_FLAG_PUBLIC); + std::shared_ptr registerPermission(const std::shared_ptr&, PermissionValue, const std::shared_ptr& channel, uint16_t = PERM_FLAG_PUBLIC); //void registerAllPermissions(uint16_t flagMask); bool setPermissionGranted(PermissionType, PermissionValue, const std::shared_ptr& channel); bool setPermission(PermissionType, PermissionValue, const std::shared_ptr& channel); - bool setPermission(PermissionType, PermissionValue, const std::shared_ptr& channel, bool negated, bool skiped); + bool setPermission(PermissionType, PermissionValue, const std::shared_ptr& channel, bool negated, bool skiped); void deletePermission(PermissionType, const std::shared_ptr& channel); bool hasPermission(PermissionType, const std::shared_ptr& channel, bool testGlobal); @@ -680,49 +680,49 @@ namespace ts { PermissionValue getPermissionGrand(permission::PermissionTestType test, PermissionType type, const std::shared_ptr& channel, PermissionValue def = permNotGranted){ PermissionValue result = def; - auto perms = this->getPermission(type, channel); - if(test == PermissionTestType::PERMTEST_HIGHEST) { - PermissionValue higest = permNotGranted; - for(const auto &e : perms) - if((e->granted > higest || e->granted == -1) && higest != -1) higest = e->granted; - if(higest != permNotGranted) - result = higest; - } else if(test == PermissionTestType::PERMTEST_ORDERED) - while(!perms.empty() && result == permNotGranted) { - result = perms.front()->granted; - perms.pop_front(); - }; + auto perms = this->getPermission(type, channel); + if(test == PermissionTestType::PERMTEST_HIGHEST) { + PermissionValue higest = permNotGranted; + for(const auto &e : perms) + if((e->granted > higest || e->granted == -1) && higest != -1) higest = e->granted; + if(higest != permNotGranted) + result = higest; + } else if(test == PermissionTestType::PERMTEST_ORDERED) + while(!perms.empty() && result == permNotGranted) { + result = perms.front()->granted; + perms.pop_front(); + }; return result; } - inline PermissionValue getPermissionValue(PermissionType type, const std::shared_ptr& channel = nullptr, PermissionValue default_value = permNotGranted) { - return this->getPermissionValue(permission::PERMTEST_ORDERED, type, channel, default_value); + inline PermissionValue getPermissionValue(PermissionType type, const std::shared_ptr& channel = nullptr, PermissionValue default_value = permNotGranted) { + return this->getPermissionValue(permission::PERMTEST_ORDERED, type, channel, default_value); } - PermissionValue getPermissionValue(permission::PermissionTestType test, PermissionType type, const std::shared_ptr& channel = nullptr, PermissionValue def = permNotGranted) { - PermissionValue result = permNotGranted; - auto perms = this->getPermission(type, channel); - if(test == permission::PERMTEST_HIGHEST) { - PermissionValue higest = permNotGranted; - for(const auto &e : perms) - if((e->value > higest || e->value == -1) && higest != -1) higest = e->value; - if(higest != permNotGranted) - result = higest; - } else if(test == PermissionTestType::PERMTEST_ORDERED) - while(!perms.empty() && result == permNotGranted) { - result = perms.front()->value; - perms.pop_front(); - }; - return result == permNotGranted ? def : result; + PermissionValue getPermissionValue(permission::PermissionTestType test, PermissionType type, const std::shared_ptr& channel = nullptr, PermissionValue def = permNotGranted) { + PermissionValue result = permNotGranted; + auto perms = this->getPermission(type, channel); + if(test == permission::PERMTEST_HIGHEST) { + PermissionValue higest = permNotGranted; + for(const auto &e : perms) + if((e->value > higest || e->value == -1) && higest != -1) higest = e->value; + if(higest != permNotGranted) + result = higest; + } else if(test == PermissionTestType::PERMTEST_ORDERED) + while(!perms.empty() && result == permNotGranted) { + result = perms.front()->value; + perms.pop_front(); + }; + return result == permNotGranted ? def : result; } std::vector> listPermissions(uint16_t = ~0); std::vector> allPermissions(); - std::deque> all_channel_specific_permissions(); - std::deque> all_channel_unspecific_permissions(); + std::deque> all_channel_specific_permissions(); + std::deque> all_channel_unspecific_permissions(); - void fireUpdate(PermissionType); + void fireUpdate(PermissionType); void registerUpdateHandler(const std::function)> &fn){ updateHandler.push_back(fn); } void clearPermissions(){ @@ -734,177 +734,177 @@ namespace ts { }; namespace v2 { - #pragma pack(push, 1) - struct PermissionFlags { - bool database_reference: 1; /* if set the permission is known within the database, else it has tp be inserted */ - bool channel_specific: 1; /* set if there are channel specific permissions */ + #pragma pack(push, 1) + struct PermissionFlags { + bool database_reference: 1; /* if set the permission is known within the database, else it has tp be inserted */ + bool channel_specific: 1; /* set if there are channel specific permissions */ - bool value_set: 1; - bool grant_set: 1; + bool value_set: 1; + bool grant_set: 1; - bool skip: 1; - bool negate: 1; + bool skip: 1; + bool negate: 1; - bool flag_value_update: 1; - bool flag_grant_update: 1; + bool flag_value_update: 1; + bool flag_grant_update: 1; - ts_always_inline bool permission_set() { - return this->value_set || this->grant_set; - } - }; - static_assert(sizeof(PermissionFlags) == 1); + ts_always_inline bool permission_set() { + return this->value_set || this->grant_set; + } + }; + static_assert(sizeof(PermissionFlags) == 1); - struct PermissionValues { - PermissionValue value; - PermissionValue grant; - }; - static_assert(sizeof(PermissionValues) == 8); - static constexpr PermissionValues empty_permission_values{0, 0}; + struct PermissionValues { + PermissionValue value; + PermissionValue grant; + }; + static_assert(sizeof(PermissionValues) == 8); + static constexpr PermissionValues empty_permission_values{0, 0}; - struct PermissionContainer { - PermissionFlags flags; - PermissionValues values; - }; - static_assert(sizeof(PermissionContainer) == 9); + struct PermissionContainer { + PermissionFlags flags; + PermissionValues values; + }; + static_assert(sizeof(PermissionContainer) == 9); - struct ChannelPermissionContainer : public PermissionContainer { - PermissionType permission; - ChannelId channel_id; - }; - static_assert(sizeof(ChannelPermissionContainer) == 19); + struct ChannelPermissionContainer : public PermissionContainer { + PermissionType permission; + ChannelId channel_id; + }; + static_assert(sizeof(ChannelPermissionContainer) == 19); - #pragma pack(pop) + #pragma pack(pop) - #pragma pack(push, 1) - template - struct PermissionContainerBulk { - PermissionContainer permissions[element_count]; + #pragma pack(push, 1) + template + struct PermissionContainerBulk { + PermissionContainer permissions[element_count]; - PermissionContainerBulk() { - memset(this->permissions, 0, sizeof(this->permissions)); - } - }; - #pragma pack(pop) + PermissionContainerBulk() { + memset(this->permissions, 0, sizeof(this->permissions)); + } + }; + #pragma pack(pop) - enum PermissionUpdateType { - do_nothing, - set_value, - delete_value - }; + enum PermissionUpdateType { + do_nothing, + set_value, + delete_value + }; - struct PermissionDBUpdateEntry { - PermissionType permission; - ChannelId channel_id; + struct PermissionDBUpdateEntry { + PermissionType permission; + ChannelId channel_id; - PermissionValues values; - PermissionUpdateType update_value; - PermissionUpdateType update_grant; + PermissionValues values; + PermissionUpdateType update_value; + PermissionUpdateType update_grant; - bool flag_db: 1; /* only needs an update if set */ - bool flag_delete: 1; - bool flag_skip: 1; - bool flag_negate: 1; - }; + bool flag_db: 1; /* only needs an update if set */ + bool flag_delete: 1; + bool flag_skip: 1; + bool flag_negate: 1; + }; - struct PermissionFlaggedValue { - PermissionValue value = permNotGranted; - bool has_value = false; - }; - static constexpr PermissionFlaggedValue empty_permission_flagged_value{0, false}; + struct PermissionFlaggedValue { + PermissionValue value = permNotGranted; + bool has_value = false; + }; + static constexpr PermissionFlaggedValue empty_permission_flagged_value{0, false}; - class PermissionManager { - public: + class PermissionManager { + public: static constexpr size_t PERMISSIONS_BULK_BITS = 4; /* 16 permissions per block */ - static constexpr size_t PERMISSIONS_BULK_ENTRY_COUNT = 1 << PERMISSIONS_BULK_BITS; + static constexpr size_t PERMISSIONS_BULK_ENTRY_COUNT = 1 << PERMISSIONS_BULK_BITS; static constexpr size_t BULK_COUNT = (PermissionType::permission_id_max / (1 << PERMISSIONS_BULK_BITS)) + ((PermissionType::permission_id_max % PERMISSIONS_BULK_ENTRY_COUNT == 0) ? 0 : 1); - static_assert(PERMISSIONS_BULK_ENTRY_COUNT * BULK_COUNT >= PermissionType::permission_id_max); + static_assert(PERMISSIONS_BULK_ENTRY_COUNT * BULK_COUNT >= PermissionType::permission_id_max); - PermissionManager(); - virtual ~PermissionManager(); + PermissionManager(); + virtual ~PermissionManager(); - /* load permissions from the database */ - void load_permission(const PermissionType&, const PermissionValues& /* values */, bool /* flag skip */, bool /* flag negate */, bool /* value present */,bool /* grant present */); - void load_permission(const PermissionType&, const PermissionValues& /* values */, ChannelId /* channel */, bool /* flag skip */, bool /* flag negate */, bool /* value present */,bool /* grant present */); + /* load permissions from the database */ + void load_permission(const PermissionType&, const PermissionValues& /* values */, bool /* flag skip */, bool /* flag negate */, bool /* value present */,bool /* grant present */); + void load_permission(const PermissionType&, const PermissionValues& /* values */, ChannelId /* channel */, bool /* flag skip */, bool /* flag negate */, bool /* value present */,bool /* grant present */); - /* general getters/setters */ - const PermissionFlags permission_flags(const PermissionType&); /* we return a "copy" because the actual permission could be deleted while we're analyzing the flags */ - ts_always_inline const PermissionFlags permission_flags(const std::shared_ptr& permission_info) { return this->permission_flags(permission_info->type); } + /* general getters/setters */ + const PermissionFlags permission_flags(const PermissionType&); /* we return a "copy" because the actual permission could be deleted while we're analyzing the flags */ + ts_always_inline const PermissionFlags permission_flags(const std::shared_ptr& permission_info) { return this->permission_flags(permission_info->type); } - const PermissionValues permission_values(const PermissionType&); - ts_always_inline const PermissionValues permission_values(const std::shared_ptr& permission_info) { return this->permission_values(permission_info->type); } + const PermissionValues permission_values(const PermissionType&); + ts_always_inline const PermissionValues permission_values(const std::shared_ptr& permission_info) { return this->permission_values(permission_info->type); } - const PermissionFlaggedValue permission_value_flagged(const PermissionType&); - ts_always_inline const PermissionFlaggedValue permission_value_flagged(const std::shared_ptr& permission_info) { return this->permission_value_flagged(permission_info->type); } + const PermissionFlaggedValue permission_value_flagged(const PermissionType&); + ts_always_inline const PermissionFlaggedValue permission_value_flagged(const std::shared_ptr& permission_info) { return this->permission_value_flagged(permission_info->type); } - const PermissionFlaggedValue permission_granted_flagged(const PermissionType&); - ts_always_inline const PermissionFlaggedValue permission_granted_flagged(const std::shared_ptr& permission_info) { return this->permission_granted_flagged(permission_info->type); } + const PermissionFlaggedValue permission_granted_flagged(const PermissionType&); + ts_always_inline const PermissionFlaggedValue permission_granted_flagged(const std::shared_ptr& permission_info) { return this->permission_granted_flagged(permission_info->type); } - /* only worth looking up if channel_specific is set */ - const PermissionContainer channel_permission(const PermissionType& /* permission */, ChannelId /* channel id */); - ts_always_inline const PermissionContainer channel_permission(const std::shared_ptr& permission_info, ChannelId channel_id) { return this->channel_permission(permission_info->type, channel_id); } + /* only worth looking up if channel_specific is set */ + const PermissionContainer channel_permission(const PermissionType& /* permission */, ChannelId /* channel id */); + ts_always_inline const PermissionContainer channel_permission(const std::shared_ptr& permission_info, ChannelId channel_id) { return this->channel_permission(permission_info->type, channel_id); } - /* modifiers */ - void set_permission(const PermissionType& /* permission */, const PermissionValues& /* values */, const PermissionUpdateType& /* update value */, const PermissionUpdateType& /* update grant */, int /* flag skip */ = -1, int /* flag negate */ = -1); - void set_channel_permission(const PermissionType& /* permission */, ChannelId /* channel id */, const PermissionValues& /* values */, const PermissionUpdateType& /* update value */, const PermissionUpdateType& /* update grant */, int /* flag skip */ = -1, int /* flag negate */ = -1); + /* modifiers */ + void set_permission(const PermissionType& /* permission */, const PermissionValues& /* values */, const PermissionUpdateType& /* update value */, const PermissionUpdateType& /* update grant */, int /* flag skip */ = -1, int /* flag negate */ = -1); + void set_channel_permission(const PermissionType& /* permission */, ChannelId /* channel id */, const PermissionValues& /* values */, const PermissionUpdateType& /* update value */, const PermissionUpdateType& /* update grant */, int /* flag skip */ = -1, int /* flag negate */ = -1); - /* bulk info */ - const std::vector> permissions(); - const std::vector> channel_permissions(ChannelId /* channel id */); - const std::vector> channel_permissions(); + /* bulk info */ + const std::vector> permissions(); + const std::vector> channel_permissions(ChannelId /* channel id */); + const std::vector> channel_permissions(); - size_t used_memory(); - void cleanup(); + size_t used_memory(); + void cleanup(); - ts_always_inline bool require_db_updates() { return this->requires_db_save; } - const std::vector flush_db_updates(); - private: - static constexpr size_t PERMISSIONS_BULK_BLOCK_MASK = (~(1 << PERMISSIONS_BULK_BITS)) & ((1 << PERMISSIONS_BULK_BITS) - 1); + ts_always_inline bool require_db_updates() { return this->requires_db_save; } + const std::vector flush_db_updates(); + private: + static constexpr size_t PERMISSIONS_BULK_BLOCK_MASK = (~(1 << PERMISSIONS_BULK_BITS)) & ((1 << PERMISSIONS_BULK_BITS) - 1); - bool requires_db_save = false; - ts_always_inline void trigger_db_update() { this->requires_db_save = true; } /* todo: pull some kind of trigger? */ + bool requires_db_save = false; + ts_always_inline void trigger_db_update() { this->requires_db_save = true; } /* todo: pull some kind of trigger? */ - spin_lock block_use_count_lock{}; - int16_t block_use_count[BULK_COUNT]; - PermissionContainerBulk* block_containers[BULK_COUNT]; + spin_lock block_use_count_lock{}; + int16_t block_use_count[BULK_COUNT]; + PermissionContainerBulk* block_containers[BULK_COUNT]; - std::shared_mutex channel_list_lock{}; - std::deque> _channel_permissions{}; + std::shared_mutex channel_list_lock{}; + std::deque> _channel_permissions{}; - ts_always_inline size_t calculate_block(const PermissionType& permission) { - return permission >> PERMISSIONS_BULK_BITS; - } + ts_always_inline size_t calculate_block(const PermissionType& permission) { + return permission >> PERMISSIONS_BULK_BITS; + } - ts_always_inline size_t calculate_block_index(const PermissionType& permission) { - return permission & PERMISSIONS_BULK_BLOCK_MASK; - } + ts_always_inline size_t calculate_block_index(const PermissionType& permission) { + return permission & PERMISSIONS_BULK_BLOCK_MASK; + } - /** - * @param block - * @return true if block exists else false - */ - ts_always_inline bool ref_block(size_t block) { - std::lock_guard use_lock(this->block_use_count_lock); - if(!this->block_containers[block]) - return false; - this->block_use_count[block]++; - assert(this->block_use_count[block] > 0); - return true; - } + /** + * @param block + * @return true if block exists else false + */ + ts_always_inline bool ref_block(size_t block) { + std::lock_guard use_lock(this->block_use_count_lock); + if(!this->block_containers[block]) + return false; + this->block_use_count[block]++; + assert(this->block_use_count[block] > 0); + return true; + } - ts_always_inline void unref_block(size_t block) { - std::lock_guard use_lock(this->block_use_count_lock); - this->block_use_count[block]--; - assert(this->block_use_count[block] >= 0); - } + ts_always_inline void unref_block(size_t block) { + std::lock_guard use_lock(this->block_use_count_lock); + this->block_use_count[block]--; + assert(this->block_use_count[block] >= 0); + } - ts_always_inline void ref_allocate_block(size_t block) { - std::lock_guard use_lock(this->block_use_count_lock); - if(!this->block_containers[block]) - this->block_containers[block] = new PermissionContainerBulk(); - this->block_use_count[block]++; - assert(this->block_use_count[block] > 0); - } - }; + ts_always_inline void ref_allocate_block(size_t block) { + std::lock_guard use_lock(this->block_use_count_lock); + if(!this->block_containers[block]) + this->block_containers[block] = new PermissionContainerBulk(); + this->block_use_count[block]++; + assert(this->block_use_count[block] > 0); + } + }; } } } diff --git a/src/Properties.cpp b/src/Properties.cpp index 969ae4c..c471959 100644 --- a/src/Properties.cpp +++ b/src/Properties.cpp @@ -10,128 +10,128 @@ using namespace ts::property; using namespace std; Properties::Properties() { - memtrack::allocated(this); + memtrack::allocated(this); } Properties::~Properties() { - memtrack::freed(this); + memtrack::freed(this); } bool Properties::has(property::PropertyType type, int index) { - for(auto it = this->properties.begin(); it != this->properties.end(); it++) { - if(!*it) continue; - if(it->get()->type != type) continue; + for(auto it = this->properties.begin(); it != this->properties.end(); it++) { + if(!*it) continue; + if(it->get()->type != type) continue; - index -= (int) it->get()->offset; - if(index < 0) return false; - return index < it->get()->length; - } - return false; + index -= (int) it->get()->offset; + if(index < 0) return false; + return index < it->get()->length; + } + return false; } PropertyWrapper Properties::find(property::PropertyType type, int index) { - for (auto &bulk : this->properties) { - if(!bulk) continue; - if(bulk->type != type) - continue; + for (auto &bulk : this->properties) { + if(!bulk) continue; + if(bulk->type != type) + continue; - index -= (int) bulk->offset; - if(index < 0) - break; + index -= (int) bulk->offset; + if(index < 0) + break; - if(index >= bulk->length) - break; + if(index >= bulk->length) + break; - return PropertyWrapper{this, &bulk->properties[index], bulk}; - } + return PropertyWrapper{this, &bulk->properties[index], bulk}; + } - throw std::invalid_argument("missing property type"); + throw std::invalid_argument("missing property type"); } std::vector Properties::list_properties(ts::property::flag_type flagMask, ts::property::flag_type negatedFlagMask) { - vector result; - result.reserve(this->properties_count); + vector result; + result.reserve(this->properties_count); - for (auto &bulk : this->properties) { - for(int index = 0; index < bulk->length; index++) { - auto& property = bulk->properties[index]; - if((property.description->flags & flagMask) > 0 && (property.description->flags & negatedFlagMask) == 0) - result.emplace_back(this, &property, bulk); - } - } + for (auto &bulk : this->properties) { + for(int index = 0; index < bulk->length; index++) { + auto& property = bulk->properties[index]; + if((property.description->flags & flagMask) > 0 && (property.description->flags & negatedFlagMask) == 0) + result.emplace_back(this, &property, bulk); + } + } return result; } std::vector Properties::all_properties() { - vector result; - result.reserve(this->properties_count); + vector result; + result.reserve(this->properties_count); - for (auto &bulk : this->properties) { - for(int index = 0; index < bulk->length; index++) - result.emplace_back(this, &bulk->properties[index], bulk); - } - return result; + for (auto &bulk : this->properties) { + for(int index = 0; index < bulk->length; index++) + result.emplace_back(this, &bulk->properties[index], bulk); + } + return result; } PropertyWrapper::PropertyWrapper(ts::Properties* handle, ts::PropertyData *data, const std::shared_ptr &bundle_lock) : handle(handle), data_ptr(data), bundle_lock(bundle_lock) { } void PropertyWrapper::trigger_update() { - this->data_ptr->flag_modified = true; + this->data_ptr->flag_modified = true; - if(this->handle) { - for(const auto& elm : this->handle->notifyFunctions) - elm(*this); - } + if(this->handle) { + for(const auto& elm : this->handle->notifyFunctions) + elm(*this); + } } bool Properties::register_property_type(ts::property::PropertyType type, size_t length, size_t offset) { - for(auto& bulk : this->properties) - if(bulk->type == type) - return false; + for(auto& bulk : this->properties) + if(bulk->type == type) + return false; - const auto alloc_length = sizeof(PropertyBundle) + sizeof(PropertyData) * length; - auto ptr = shared_ptr((PropertyBundle*) malloc(alloc_length), [](PropertyBundle* bundle) { - if(!bundle) return; + const auto alloc_length = sizeof(PropertyBundle) + sizeof(PropertyData) * length; + auto ptr = shared_ptr((PropertyBundle*) malloc(alloc_length), [](PropertyBundle* bundle) { + if(!bundle) return; - for(int index = 0; index < bundle->length; index++) { - auto& property = bundle->properties[index]; - property.description.~shared_ptr(); - property.value.~string(); - property.value_lock.~spin_lock(); - property.casted_value.~any(); - } - ::free(bundle); - }); + for(int index = 0; index < bundle->length; index++) { + auto& property = bundle->properties[index]; + property.description.~shared_ptr(); + property.value.~string(); + property.value_lock.~spin_lock(); + property.casted_value.~any(); + } + ::free(bundle); + }); - ptr->type = type; - ptr->offset = offset; - ptr->length = length; + ptr->type = type; + ptr->offset = offset; + ptr->length = length; - for(int index = 0; index < length; index++) { - auto& property = ptr->properties[index]; + for(int index = 0; index < length; index++) { + auto& property = ptr->properties[index]; - new (&property.casted_value) any(); - new (&property.value_lock) spin_lock(); - new (&property.value) string(); - new (&property.description) shared_ptr(property::impl::info(type, (int) (offset + index))); - property.flag_modified = false; - property.flag_db_reference = false; + new (&property.casted_value) any(); + new (&property.value_lock) spin_lock(); + new (&property.value) string(); + new (&property.description) shared_ptr(property::impl::info(type, (int) (offset + index))); + property.flag_modified = false; + property.flag_db_reference = false; - property.value = property.description->default_value; - this->properties_count++; - } + property.value = property.description->default_value; + this->properties_count++; + } - this->properties.push_back(ptr); - return false; + this->properties.push_back(ptr); + return false; } namespace ts { - namespace property { - PropertyDescription::PropertyDescription(int property_id, PropertyType property_type, const std::string &name, const std::string &default_value, property::ValueType type, property::flag_type flags) noexcept : name(name), default_value(default_value), - type_value(type), flags(flags), property_index(property_id), - type_property(property_type) { - std::transform(this->name.begin(), this->name.end(), this->name.begin(), ::tolower); - } + namespace property { + PropertyDescription::PropertyDescription(int property_id, PropertyType property_type, const std::string &name, const std::string &default_value, property::ValueType type, property::flag_type flags) noexcept : name(name), default_value(default_value), + type_value(type), flags(flags), property_index(property_id), + type_property(property_type) { + std::transform(this->name.begin(), this->name.end(), this->name.begin(), ::tolower); + } #define FLAG_SS (FLAG_SNAPSHOT | FLAG_SAVE) #define FLAG_SERVER_VV (FLAG_SERVER_VARIABLE | FLAG_SERVER_VIEW) @@ -140,396 +140,396 @@ namespace ts { #define FLAG_CLIENT_VV (FLAG_CLIENT_VARIABLE | FLAG_CLIENT_VIEW) #define FLAG_CLIENT_VVSS (FLAG_CLIENT_VV | FLAG_SS) - array, VirtualServerProperties::VIRTUALSERVER_ENDMARKER> virtualserver_info = { - make_shared(VIRTUALSERVER_UNDEFINED, "VIRTUALSERVER_UNDEFINED", "", TYPE_UNKNOWN, 0), //Must be at index 0! - make_shared(VIRTUALSERVER_ID, "VIRTUALSERVER_ID", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VIEW), //available when connected - make_shared(VIRTUALSERVER_UNIQUE_IDENTIFIER, "VIRTUALSERVER_UNIQUE_IDENTIFIER", "", TYPE_STRING, FLAG_SERVER_VV | FLAG_SNAPSHOT), - make_shared(VIRTUALSERVER_NAME, "VIRTUALSERVER_NAME", "Another TeaSpeak server software user", TYPE_STRING, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), - make_shared(VIRTUALSERVER_WELCOMEMESSAGE, "VIRTUALSERVER_WELCOMEMESSAGE", "Welcome on another TeaSpeak server. (Download now and a license fee is not your cup of tea! [URL]www.teaspeak.de[/URL])", TYPE_STRING, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), - make_shared(VIRTUALSERVER_PLATFORM, "VIRTUALSERVER_PLATFORM", "undefined", TYPE_STRING, FLAG_SERVER_VIEW), - make_shared(VIRTUALSERVER_VERSION, "VIRTUALSERVER_VERSION", "undefined", TYPE_STRING, FLAG_SERVER_VIEW), - make_shared(VIRTUALSERVER_MAXCLIENTS, "VIRTUALSERVER_MAXCLIENTS", "120", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), - make_shared(VIRTUALSERVER_PASSWORD, "VIRTUALSERVER_PASSWORD", "", TYPE_STRING, FLAG_SS | FLAG_USER_EDITABLE), - make_shared(VIRTUALSERVER_CLIENTS_ONLINE, "virtualserver_clientsonline", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE), - make_shared(VIRTUALSERVER_CHANNELS_ONLINE, "virtualserver_channelsonline", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE), //only available on request (=> requestServerVariables), - make_shared(VIRTUALSERVER_QUERYCLIENTS_ONLINE, "virtualserver_queryclientsonline", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_CREATED, "VIRTUALSERVER_CREATED", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VIEW | FLAG_SS), //available when connected, stores the time when the server was created - make_shared(VIRTUALSERVER_UPTIME, "VIRTUALSERVER_UPTIME", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE), //only available on request (=> requestServerVariables), the time since the server was started - make_shared(VIRTUALSERVER_CODEC_ENCRYPTION_MODE, "VIRTUALSERVER_CODEC_ENCRYPTION_MODE", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), //available and always up-to-date when connected + array, VirtualServerProperties::VIRTUALSERVER_ENDMARKER> virtualserver_info = { + make_shared(VIRTUALSERVER_UNDEFINED, "VIRTUALSERVER_UNDEFINED", "", TYPE_UNKNOWN, 0), //Must be at index 0! + make_shared(VIRTUALSERVER_ID, "VIRTUALSERVER_ID", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VIEW), //available when connected + make_shared(VIRTUALSERVER_UNIQUE_IDENTIFIER, "VIRTUALSERVER_UNIQUE_IDENTIFIER", "", TYPE_STRING, FLAG_SERVER_VV | FLAG_SNAPSHOT), + make_shared(VIRTUALSERVER_NAME, "VIRTUALSERVER_NAME", "Another TeaSpeak server software user", TYPE_STRING, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), + make_shared(VIRTUALSERVER_WELCOMEMESSAGE, "VIRTUALSERVER_WELCOMEMESSAGE", "Welcome on another TeaSpeak server. (Download now and a license fee is not your cup of tea! [URL]www.teaspeak.de[/URL])", TYPE_STRING, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), + make_shared(VIRTUALSERVER_PLATFORM, "VIRTUALSERVER_PLATFORM", "undefined", TYPE_STRING, FLAG_SERVER_VIEW), + make_shared(VIRTUALSERVER_VERSION, "VIRTUALSERVER_VERSION", "undefined", TYPE_STRING, FLAG_SERVER_VIEW), + make_shared(VIRTUALSERVER_MAXCLIENTS, "VIRTUALSERVER_MAXCLIENTS", "120", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), + make_shared(VIRTUALSERVER_PASSWORD, "VIRTUALSERVER_PASSWORD", "", TYPE_STRING, FLAG_SS | FLAG_USER_EDITABLE), + make_shared(VIRTUALSERVER_CLIENTS_ONLINE, "virtualserver_clientsonline", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE), + make_shared(VIRTUALSERVER_CHANNELS_ONLINE, "virtualserver_channelsonline", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE), //only available on request (=> requestServerVariables), + make_shared(VIRTUALSERVER_QUERYCLIENTS_ONLINE, "virtualserver_queryclientsonline", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_CREATED, "VIRTUALSERVER_CREATED", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VIEW | FLAG_SS), //available when connected, stores the time when the server was created + make_shared(VIRTUALSERVER_UPTIME, "VIRTUALSERVER_UPTIME", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE), //only available on request (=> requestServerVariables), the time since the server was started + make_shared(VIRTUALSERVER_CODEC_ENCRYPTION_MODE, "VIRTUALSERVER_CODEC_ENCRYPTION_MODE", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), //available and always up-to-date when connected - // Rare properties - make_shared(VIRTUALSERVER_KEYPAIR, "VIRTUALSERVER_KEYPAIR", "", TYPE_STRING, FLAG_SS), //internal use - make_shared(VIRTUALSERVER_HOSTMESSAGE, "VIRTUALSERVER_HOSTMESSAGE", "Welcome", TYPE_STRING, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), //available when connected, not updated while connected - make_shared(VIRTUALSERVER_HOSTMESSAGE_MODE, "VIRTUALSERVER_HOSTMESSAGE_MODE", "1", TYPE_STRING, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), //available when connected, not updated while connected - make_shared(VIRTUALSERVER_DEFAULT_SERVER_GROUP, "VIRTUALSERVER_DEFAULT_SERVER_GROUP", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), //the manager permissions server group that a new manager gets assigned - make_shared(VIRTUALSERVER_DEFAULT_MUSIC_GROUP, "VIRTUALSERVER_DEFAULT_MUSIC_GROUP", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), //the manager permissions server group that a new manager gets assigned - make_shared(VIRTUALSERVER_DEFAULT_CHANNEL_GROUP, "VIRTUALSERVER_DEFAULT_CHANNEL_GROUP", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), //the channel permissions group that a new manager gets assigned when joining a channel - make_shared(VIRTUALSERVER_FLAG_PASSWORD, "VIRTUALSERVER_FLAG_PASSWORD", "0", TYPE_BOOL, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_DEFAULT_CHANNEL_ADMIN_GROUP, "VIRTUALSERVER_DEFAULT_CHANNEL_ADMIN_GROUP", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SERVER_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //the channel permissions group that a manager gets assigned when creating a channel - make_shared(VIRTUALSERVER_MAX_DOWNLOAD_TOTAL_BANDWIDTH, "VIRTUALSERVER_MAX_DOWNLOAD_TOTAL_BANDWIDTH", "-1", TYPE_SIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_MAX_UPLOAD_TOTAL_BANDWIDTH, "VIRTUALSERVER_MAX_UPLOAD_TOTAL_BANDWIDTH", "-1", TYPE_SIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_HOSTBANNER_URL, "VIRTUALSERVER_HOSTBANNER_URL", "", TYPE_STRING, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), //available when connected, always up-to-date - make_shared(VIRTUALSERVER_HOSTBANNER_GFX_URL, "VIRTUALSERVER_HOSTBANNER_GFX_URL", "", TYPE_STRING, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), //available when connected, always up-to-date - make_shared(VIRTUALSERVER_HOSTBANNER_GFX_INTERVAL, "VIRTUALSERVER_HOSTBANNER_GFX_INTERVAL", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), //available when connected, always up-to-date - make_shared(VIRTUALSERVER_COMPLAIN_AUTOBAN_COUNT, "VIRTUALSERVER_COMPLAIN_AUTOBAN_COUNT", "5", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_COMPLAIN_AUTOBAN_TIME, "VIRTUALSERVER_COMPLAIN_AUTOBAN_TIME", "5", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_COMPLAIN_REMOVE_TIME, "VIRTUALSERVER_COMPLAIN_REMOVE_TIME", "5", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_MIN_CLIENTS_IN_CHANNEL_BEFORE_FORCED_SILENCE, "VIRTUALSERVER_MIN_CLIENTS_IN_CHANNEL_BEFORE_FORCED_SILENCE", "20", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE),//only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_PRIORITY_SPEAKER_DIMM_MODIFICATOR, "VIRTUALSERVER_PRIORITY_SPEAKER_DIMM_MODIFICATOR", "-18", TYPE_FLOAT, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), //available when connected, always up-to-date - make_shared(VIRTUALSERVER_ANTIFLOOD_POINTS_TICK_REDUCE, "VIRTUALSERVER_ANTIFLOOD_POINTS_TICK_REDUCE", "25", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_ANTIFLOOD_POINTS_NEEDED_COMMAND_BLOCK, "VIRTUALSERVER_ANTIFLOOD_POINTS_NEEDED_COMMAND_BLOCK", "150", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_ANTIFLOOD_POINTS_NEEDED_IP_BLOCK, "VIRTUALSERVER_ANTIFLOOD_POINTS_NEEDED_IP_BLOCK", "300", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_CLIENT_CONNECTIONS, "VIRTUALSERVER_CLIENT_CONNECTIONS", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_QUERY_CLIENT_CONNECTIONS, "VIRTUALSERVER_QUERY_CLIENT_CONNECTIONS", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_HOSTBUTTON_TOOLTIP, "VIRTUALSERVER_HOSTBUTTON_TOOLTIP", "", TYPE_STRING, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), //available when connected, always up-to-date - make_shared(VIRTUALSERVER_HOSTBUTTON_URL, "VIRTUALSERVER_HOSTBUTTON_URL", "", TYPE_STRING, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), //available when connected, always up-to-date - make_shared(VIRTUALSERVER_HOSTBUTTON_GFX_URL, "VIRTUALSERVER_HOSTBUTTON_GFX_URL", "", TYPE_STRING, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), //available when connected, always up-to-date - make_shared(VIRTUALSERVER_HOSTBANNER_MODE, "VIRTUALSERVER_HOSTBANNER_MODE", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), //available when connected, always up-to-date - make_shared(VIRTUALSERVER_FILEBASE, "VIRTUALSERVER_FILEBASE", "", TYPE_STRING, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //not available to clients, stores the folder used for file transfers - make_shared(VIRTUALSERVER_DOWNLOAD_QUOTA, "VIRTUALSERVER_DOWNLOAD_QUOTA", "-1", TYPE_SIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SAVE | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_UPLOAD_QUOTA, "VIRTUALSERVER_UPLOAD_QUOTA", "-1", TYPE_SIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SAVE | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_MONTH_BYTES_DOWNLOADED, "VIRTUALSERVER_MONTH_BYTES_DOWNLOADED", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SAVE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_MONTH_BYTES_UPLOADED, "VIRTUALSERVER_MONTH_BYTES_UPLOADED", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SAVE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_TOTAL_BYTES_DOWNLOADED, "VIRTUALSERVER_TOTAL_BYTES_DOWNLOADED", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SAVE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_TOTAL_BYTES_UPLOADED, "VIRTUALSERVER_TOTAL_BYTES_UPLOADED", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SAVE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_PORT, "VIRTUALSERVER_PORT", "9987", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_HOST, "VIRTUALSERVER_HOST", "0.0.0.0,::", TYPE_STRING, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //internal use | contains comma separated ip list - make_shared(VIRTUALSERVER_AUTOSTART, "VIRTUALSERVER_AUTOSTART", "1", TYPE_BOOL, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_MACHINE_ID, "VIRTUALSERVER_MACHINE_ID", "", TYPE_STRING, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_NEEDED_IDENTITY_SECURITY_LEVEL, "VIRTUALSERVER_NEEDED_IDENTITY_SECURITY_LEVEL", "8", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_LOG_CLIENT, "VIRTUALSERVER_LOG_CLIENT", "1", TYPE_BOOL, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_LOG_QUERY, "VIRTUALSERVER_LOG_QUERY", "1", TYPE_BOOL, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_LOG_CHANNEL, "VIRTUALSERVER_LOG_CHANNEL", "1", TYPE_BOOL, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_LOG_PERMISSIONS, "VIRTUALSERVER_LOG_PERMISSIONS", "1", TYPE_BOOL, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_LOG_SERVER, "VIRTUALSERVER_LOG_SERVER", "1", TYPE_BOOL, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_LOG_FILETRANSFER, "VIRTUALSERVER_LOG_FILETRANSFER", "1", TYPE_BOOL, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_NAME_PHONETIC, "VIRTUALSERVER_NAME_PHONETIC", "", TYPE_STRING, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), //available when connected, always up-to-date - make_shared(VIRTUALSERVER_ICON_ID, "VIRTUALSERVER_ICON_ID", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), //available when connected, always up-to-date - make_shared(VIRTUALSERVER_RESERVED_SLOTS, "VIRTUALSERVER_RESERVED_SLOTS", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //available when connected, always up-to-date - make_shared(VIRTUALSERVER_TOTAL_PACKETLOSS_SPEECH, "VIRTUALSERVER_TOTAL_PACKETLOSS_SPEECH", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_TOTAL_PACKETLOSS_KEEPALIVE, "VIRTUALSERVER_TOTAL_PACKETLOSS_KEEPALIVE", "0", TYPE_FLOAT, FLAG_SERVER_VARIABLE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_TOTAL_PACKETLOSS_CONTROL, "VIRTUALSERVER_TOTAL_PACKETLOSS_CONTROL", "0", TYPE_FLOAT, FLAG_SERVER_VARIABLE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_TOTAL_PACKETLOSS_TOTAL, "VIRTUALSERVER_TOTAL_PACKETLOSS_TOTAL", "0", TYPE_FLOAT, FLAG_SERVER_VARIABLE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_TOTAL_PING, "VIRTUALSERVER_TOTAL_PING", "0", TYPE_FLOAT, FLAG_SERVER_VARIABLE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_WEBLIST_ENABLED, "VIRTUALSERVER_WEBLIST_ENABLED", "1", TYPE_BOOL, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_AUTOGENERATED_PRIVILEGEKEY, "VIRTUALSERVER_AUTOGENERATED_PRIVILEGEKEY", "", TYPE_STRING, FLAG_SAVE), //internal use - make_shared(VIRTUALSERVER_ASK_FOR_PRIVILEGEKEY, "VIRTUALSERVER_ASK_FOR_PRIVILEGEKEY", "1", TYPE_BOOL, FLAG_SERVER_VV | FLAG_SAVE | FLAG_USER_EDITABLE), //available when connected - make_shared(VIRTUALSERVER_CHANNEL_TEMP_DELETE_DELAY_DEFAULT, "VIRTUALSERVER_CHANNEL_TEMP_DELETE_DELAY_DEFAULT", "60", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), //available when connected, always up-to-date - make_shared(VIRTUALSERVER_MIN_CLIENT_VERSION, "VIRTUALSERVER_MIN_CLIENT_VERSION", "1445512488", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_MIN_ANDROID_VERSION, "VIRTUALSERVER_MIN_ANDROID_VERSION", "1407159763", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_MIN_IOS_VERSION, "VIRTUALSERVER_MIN_IOS_VERSION", "1407159763", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_MIN_WINPHONE_VERSION, "VIRTUALSERVER_MIN_WINPHONE_VERSION", "1407159763", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) + // Rare properties + make_shared(VIRTUALSERVER_KEYPAIR, "VIRTUALSERVER_KEYPAIR", "", TYPE_STRING, FLAG_SS), //internal use + make_shared(VIRTUALSERVER_HOSTMESSAGE, "VIRTUALSERVER_HOSTMESSAGE", "Welcome", TYPE_STRING, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), //available when connected, not updated while connected + make_shared(VIRTUALSERVER_HOSTMESSAGE_MODE, "VIRTUALSERVER_HOSTMESSAGE_MODE", "1", TYPE_STRING, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), //available when connected, not updated while connected + make_shared(VIRTUALSERVER_DEFAULT_SERVER_GROUP, "VIRTUALSERVER_DEFAULT_SERVER_GROUP", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), //the manager permissions server group that a new manager gets assigned + make_shared(VIRTUALSERVER_DEFAULT_MUSIC_GROUP, "VIRTUALSERVER_DEFAULT_MUSIC_GROUP", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), //the manager permissions server group that a new manager gets assigned + make_shared(VIRTUALSERVER_DEFAULT_CHANNEL_GROUP, "VIRTUALSERVER_DEFAULT_CHANNEL_GROUP", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), //the channel permissions group that a new manager gets assigned when joining a channel + make_shared(VIRTUALSERVER_FLAG_PASSWORD, "VIRTUALSERVER_FLAG_PASSWORD", "0", TYPE_BOOL, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_DEFAULT_CHANNEL_ADMIN_GROUP, "VIRTUALSERVER_DEFAULT_CHANNEL_ADMIN_GROUP", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SERVER_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //the channel permissions group that a manager gets assigned when creating a channel + make_shared(VIRTUALSERVER_MAX_DOWNLOAD_TOTAL_BANDWIDTH, "VIRTUALSERVER_MAX_DOWNLOAD_TOTAL_BANDWIDTH", "-1", TYPE_SIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_MAX_UPLOAD_TOTAL_BANDWIDTH, "VIRTUALSERVER_MAX_UPLOAD_TOTAL_BANDWIDTH", "-1", TYPE_SIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_HOSTBANNER_URL, "VIRTUALSERVER_HOSTBANNER_URL", "", TYPE_STRING, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), //available when connected, always up-to-date + make_shared(VIRTUALSERVER_HOSTBANNER_GFX_URL, "VIRTUALSERVER_HOSTBANNER_GFX_URL", "", TYPE_STRING, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), //available when connected, always up-to-date + make_shared(VIRTUALSERVER_HOSTBANNER_GFX_INTERVAL, "VIRTUALSERVER_HOSTBANNER_GFX_INTERVAL", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), //available when connected, always up-to-date + make_shared(VIRTUALSERVER_COMPLAIN_AUTOBAN_COUNT, "VIRTUALSERVER_COMPLAIN_AUTOBAN_COUNT", "5", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_COMPLAIN_AUTOBAN_TIME, "VIRTUALSERVER_COMPLAIN_AUTOBAN_TIME", "5", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_COMPLAIN_REMOVE_TIME, "VIRTUALSERVER_COMPLAIN_REMOVE_TIME", "5", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_MIN_CLIENTS_IN_CHANNEL_BEFORE_FORCED_SILENCE, "VIRTUALSERVER_MIN_CLIENTS_IN_CHANNEL_BEFORE_FORCED_SILENCE", "20", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE),//only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_PRIORITY_SPEAKER_DIMM_MODIFICATOR, "VIRTUALSERVER_PRIORITY_SPEAKER_DIMM_MODIFICATOR", "-18", TYPE_FLOAT, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), //available when connected, always up-to-date + make_shared(VIRTUALSERVER_ANTIFLOOD_POINTS_TICK_REDUCE, "VIRTUALSERVER_ANTIFLOOD_POINTS_TICK_REDUCE", "25", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_ANTIFLOOD_POINTS_NEEDED_COMMAND_BLOCK, "VIRTUALSERVER_ANTIFLOOD_POINTS_NEEDED_COMMAND_BLOCK", "150", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_ANTIFLOOD_POINTS_NEEDED_IP_BLOCK, "VIRTUALSERVER_ANTIFLOOD_POINTS_NEEDED_IP_BLOCK", "300", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_CLIENT_CONNECTIONS, "VIRTUALSERVER_CLIENT_CONNECTIONS", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_QUERY_CLIENT_CONNECTIONS, "VIRTUALSERVER_QUERY_CLIENT_CONNECTIONS", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_HOSTBUTTON_TOOLTIP, "VIRTUALSERVER_HOSTBUTTON_TOOLTIP", "", TYPE_STRING, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), //available when connected, always up-to-date + make_shared(VIRTUALSERVER_HOSTBUTTON_URL, "VIRTUALSERVER_HOSTBUTTON_URL", "", TYPE_STRING, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), //available when connected, always up-to-date + make_shared(VIRTUALSERVER_HOSTBUTTON_GFX_URL, "VIRTUALSERVER_HOSTBUTTON_GFX_URL", "", TYPE_STRING, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), //available when connected, always up-to-date + make_shared(VIRTUALSERVER_HOSTBANNER_MODE, "VIRTUALSERVER_HOSTBANNER_MODE", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), //available when connected, always up-to-date + make_shared(VIRTUALSERVER_FILEBASE, "VIRTUALSERVER_FILEBASE", "", TYPE_STRING, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //not available to clients, stores the folder used for file transfers + make_shared(VIRTUALSERVER_DOWNLOAD_QUOTA, "VIRTUALSERVER_DOWNLOAD_QUOTA", "-1", TYPE_SIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SAVE | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_UPLOAD_QUOTA, "VIRTUALSERVER_UPLOAD_QUOTA", "-1", TYPE_SIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SAVE | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_MONTH_BYTES_DOWNLOADED, "VIRTUALSERVER_MONTH_BYTES_DOWNLOADED", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SAVE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_MONTH_BYTES_UPLOADED, "VIRTUALSERVER_MONTH_BYTES_UPLOADED", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SAVE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_TOTAL_BYTES_DOWNLOADED, "VIRTUALSERVER_TOTAL_BYTES_DOWNLOADED", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SAVE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_TOTAL_BYTES_UPLOADED, "VIRTUALSERVER_TOTAL_BYTES_UPLOADED", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SAVE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_PORT, "VIRTUALSERVER_PORT", "9987", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_HOST, "VIRTUALSERVER_HOST", "0.0.0.0,::", TYPE_STRING, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //internal use | contains comma separated ip list + make_shared(VIRTUALSERVER_AUTOSTART, "VIRTUALSERVER_AUTOSTART", "1", TYPE_BOOL, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_MACHINE_ID, "VIRTUALSERVER_MACHINE_ID", "", TYPE_STRING, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_NEEDED_IDENTITY_SECURITY_LEVEL, "VIRTUALSERVER_NEEDED_IDENTITY_SECURITY_LEVEL", "8", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_LOG_CLIENT, "VIRTUALSERVER_LOG_CLIENT", "1", TYPE_BOOL, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_LOG_QUERY, "VIRTUALSERVER_LOG_QUERY", "1", TYPE_BOOL, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_LOG_CHANNEL, "VIRTUALSERVER_LOG_CHANNEL", "1", TYPE_BOOL, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_LOG_PERMISSIONS, "VIRTUALSERVER_LOG_PERMISSIONS", "1", TYPE_BOOL, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_LOG_SERVER, "VIRTUALSERVER_LOG_SERVER", "1", TYPE_BOOL, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_LOG_FILETRANSFER, "VIRTUALSERVER_LOG_FILETRANSFER", "1", TYPE_BOOL, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_NAME_PHONETIC, "VIRTUALSERVER_NAME_PHONETIC", "", TYPE_STRING, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), //available when connected, always up-to-date + make_shared(VIRTUALSERVER_ICON_ID, "VIRTUALSERVER_ICON_ID", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), //available when connected, always up-to-date + make_shared(VIRTUALSERVER_RESERVED_SLOTS, "VIRTUALSERVER_RESERVED_SLOTS", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //available when connected, always up-to-date + make_shared(VIRTUALSERVER_TOTAL_PACKETLOSS_SPEECH, "VIRTUALSERVER_TOTAL_PACKETLOSS_SPEECH", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_TOTAL_PACKETLOSS_KEEPALIVE, "VIRTUALSERVER_TOTAL_PACKETLOSS_KEEPALIVE", "0", TYPE_FLOAT, FLAG_SERVER_VARIABLE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_TOTAL_PACKETLOSS_CONTROL, "VIRTUALSERVER_TOTAL_PACKETLOSS_CONTROL", "0", TYPE_FLOAT, FLAG_SERVER_VARIABLE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_TOTAL_PACKETLOSS_TOTAL, "VIRTUALSERVER_TOTAL_PACKETLOSS_TOTAL", "0", TYPE_FLOAT, FLAG_SERVER_VARIABLE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_TOTAL_PING, "VIRTUALSERVER_TOTAL_PING", "0", TYPE_FLOAT, FLAG_SERVER_VARIABLE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_WEBLIST_ENABLED, "VIRTUALSERVER_WEBLIST_ENABLED", "1", TYPE_BOOL, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_AUTOGENERATED_PRIVILEGEKEY, "VIRTUALSERVER_AUTOGENERATED_PRIVILEGEKEY", "", TYPE_STRING, FLAG_SAVE), //internal use + make_shared(VIRTUALSERVER_ASK_FOR_PRIVILEGEKEY, "VIRTUALSERVER_ASK_FOR_PRIVILEGEKEY", "1", TYPE_BOOL, FLAG_SERVER_VV | FLAG_SAVE | FLAG_USER_EDITABLE), //available when connected + make_shared(VIRTUALSERVER_CHANNEL_TEMP_DELETE_DELAY_DEFAULT, "VIRTUALSERVER_CHANNEL_TEMP_DELETE_DELAY_DEFAULT", "60", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE), //available when connected, always up-to-date + make_shared(VIRTUALSERVER_MIN_CLIENT_VERSION, "VIRTUALSERVER_MIN_CLIENT_VERSION", "1445512488", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_MIN_ANDROID_VERSION, "VIRTUALSERVER_MIN_ANDROID_VERSION", "1407159763", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_MIN_IOS_VERSION, "VIRTUALSERVER_MIN_IOS_VERSION", "1407159763", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_MIN_WINPHONE_VERSION, "VIRTUALSERVER_MIN_WINPHONE_VERSION", "1407159763", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_LAST_CLIENT_CONNECT, "VIRTUALSERVER_LAST_CLIENT_CONNECT", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_NEW | FLAG_SS), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_LAST_QUERY_CONNECT, "VIRTUALSERVER_LAST_QUERY_CONNECT", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_NEW | FLAG_SS), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_LAST_CLIENT_DISCONNECT, "VIRTUALSERVER_LAST_CLIENT_DISCONNECT", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_NEW | FLAG_SS), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_LAST_QUERY_DISCONNECT, "VIRTUALSERVER_LAST_QUERY_DISCONNECT", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_NEW | FLAG_SS), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_LAST_CLIENT_CONNECT, "VIRTUALSERVER_LAST_CLIENT_CONNECT", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_NEW | FLAG_SS), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_LAST_QUERY_CONNECT, "VIRTUALSERVER_LAST_QUERY_CONNECT", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_NEW | FLAG_SS), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_LAST_CLIENT_DISCONNECT, "VIRTUALSERVER_LAST_CLIENT_DISCONNECT", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_NEW | FLAG_SS), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_LAST_QUERY_DISCONNECT, "VIRTUALSERVER_LAST_QUERY_DISCONNECT", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_NEW | FLAG_SS), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_WEB_PORT, "VIRTUALSERVER_WEB_PORT", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_NEW | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_WEB_HOST, "VIRTUALSERVER_WEB_HOST", "0.0.0.0", TYPE_STRING, FLAG_SERVER_VARIABLE | FLAG_NEW | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_WEB_PORT, "VIRTUALSERVER_WEB_PORT", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_NEW | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_WEB_HOST, "VIRTUALSERVER_WEB_HOST", "0.0.0.0", TYPE_STRING, FLAG_SERVER_VARIABLE | FLAG_NEW | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) make_shared(VIRTUALSERVER_DEFAULT_CLIENT_DESCRIPTION, "VIRTUALSERVER_DEFAULT_CLIENT_DESCRIPTION", "", TYPE_STRING, FLAG_SERVER_VARIABLE | FLAG_NEW | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) make_shared(VIRTUALSERVER_DEFAULT_CHANNEL_DESCRIPTION, "VIRTUALSERVER_DEFAULT_CHANNEL_DESCRIPTION", "", TYPE_STRING, FLAG_SERVER_VARIABLE | FLAG_NEW | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_DEFAULT_CHANNEL_TOPIC, "VIRTUALSERVER_DEFAULT_CHANNEL_TOPIC", "", TYPE_STRING, FLAG_SERVER_VARIABLE | FLAG_NEW | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_DEFAULT_CHANNEL_TOPIC, "VIRTUALSERVER_DEFAULT_CHANNEL_TOPIC", "", TYPE_STRING, FLAG_SERVER_VARIABLE | FLAG_NEW | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_MUSIC_BOT_LIMIT, "VIRTUALSERVER_MUSIC_BOT_LIMIT", "-1", TYPE_SIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_NEW | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_SPOKEN_TIME, "VIRTUALSERVER_SPOKEN_TIME", "0", TYPE_UNSIGNED_NUMBER, FLAG_INTERNAL | FLAG_NEW | FLAG_SAVE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_DISABLE_IP_SAVING, "VIRTUALSERVER_DISABLE_IP_SAVING", "0", TYPE_BOOL, FLAG_INTERNAL | FLAG_NEW | FLAG_SAVE | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) - make_shared(VIRTUALSERVER_COUNTRY_CODE, "VIRTUALSERVER_COUNTRY_CODE", "XX", TYPE_STRING, FLAG_SERVER_VV | FLAG_SAVE | FLAG_USER_EDITABLE) //available when connected - }; + make_shared(VIRTUALSERVER_MUSIC_BOT_LIMIT, "VIRTUALSERVER_MUSIC_BOT_LIMIT", "-1", TYPE_SIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_NEW | FLAG_SS | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_SPOKEN_TIME, "VIRTUALSERVER_SPOKEN_TIME", "0", TYPE_UNSIGNED_NUMBER, FLAG_INTERNAL | FLAG_NEW | FLAG_SAVE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_DISABLE_IP_SAVING, "VIRTUALSERVER_DISABLE_IP_SAVING", "0", TYPE_BOOL, FLAG_INTERNAL | FLAG_NEW | FLAG_SAVE | FLAG_USER_EDITABLE), //only available on request (=> requestServerVariables) + make_shared(VIRTUALSERVER_COUNTRY_CODE, "VIRTUALSERVER_COUNTRY_CODE", "XX", TYPE_STRING, FLAG_SERVER_VV | FLAG_SAVE | FLAG_USER_EDITABLE) //available when connected + }; - array, ChannelProperties::CHANNEL_ENDMARKER> channel_info = { - make_shared(CHANNEL_UNDEFINED, "CHANNEL_UNDEFINED", "", TYPE_UNKNOWN, 0), //Must be at index 0! - make_shared(CHANNEL_ID, "cid", "0", TYPE_UNSIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS), - make_shared(CHANNEL_PID, "cpid", "0", TYPE_UNSIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS), - make_shared(CHANNEL_NAME, "CHANNEL_NAME", "undefined", TYPE_STRING, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //Available for all channels that are "in view", always up-to-date - make_shared(CHANNEL_TOPIC, "CHANNEL_TOPIC", "", TYPE_STRING, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //Available for all channels that are "in view", always up-to-date - make_shared(CHANNEL_DESCRIPTION, "CHANNEL_DESCRIPTION", "", TYPE_STRING, FLAG_CHANNEL_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //Must be requested (=> requestChannelDescription) - make_shared(CHANNEL_PASSWORD, "CHANNEL_PASSWORD", "0", TYPE_STRING, FLAG_SS | FLAG_USER_EDITABLE), //not available manager side - make_shared(CHANNEL_CODEC, "CHANNEL_CODEC", "4", TYPE_UNSIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //Available for all channels that are "in view", always up-to-date - make_shared(CHANNEL_CODEC_QUALITY, "CHANNEL_CODEC_QUALITY", "7", TYPE_UNSIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //Available for all channels that are "in view", always up-to-date - make_shared(CHANNEL_MAXCLIENTS, "CHANNEL_MAXCLIENTS", "-1", TYPE_SIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //Available for all channels that are "in view", always up-to-date - make_shared(CHANNEL_MAXFAMILYCLIENTS, "CHANNEL_MAXFAMILYCLIENTS", "-1", TYPE_SIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //Available for all channels that are "in view", always up-to-date - make_shared(CHANNEL_ORDER, "CHANNEL_ORDER", "0", TYPE_UNSIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //Available for all channels that are "in view", always up-to-date - make_shared(CHANNEL_FLAG_PERMANENT, "CHANNEL_FLAG_PERMANENT", "1", TYPE_BOOL, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //Available for all channels that are "in view", always up-to-date - make_shared(CHANNEL_FLAG_SEMI_PERMANENT, "CHANNEL_FLAG_SEMI_PERMANENT", "0", TYPE_BOOL, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //Available for all channels that are "in view", always up-to-date - make_shared(CHANNEL_FLAG_DEFAULT, "CHANNEL_FLAG_DEFAULT", "0", TYPE_BOOL, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //Available for all channels that are "in view", always up-to-date - make_shared(CHANNEL_FLAG_PASSWORD, "CHANNEL_FLAG_PASSWORD", "0", TYPE_BOOL, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //Available for all channels that are "in view", always up-to-date - make_shared(CHANNEL_CODEC_LATENCY_FACTOR, "CHANNEL_CODEC_LATENCY_FACTOR", "1", TYPE_UNSIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //Available for all channels that are "in view", always up-to-date - make_shared(CHANNEL_CODEC_IS_UNENCRYPTED, "CHANNEL_CODEC_IS_UNENCRYPTED", "1", TYPE_BOOL, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //Available for all channels that are "in view", always up-to-date - make_shared(CHANNEL_SECURITY_SALT, "CHANNEL_SECURITY_SALT", "", TYPE_STRING, FLAG_SS), //Not available manager side, not used in teamspeak, only SDK. Sets the options+salt for security hash. - make_shared(CHANNEL_DELETE_DELAY, "CHANNEL_DELETE_DELAY", "0", TYPE_UNSIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //How many seconds to wait before deleting this channel - make_shared(CHANNEL_FLAG_MAXCLIENTS_UNLIMITED, "CHANNEL_FLAG_MAXCLIENTS_UNLIMITED", "1", TYPE_BOOL, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //Available for all channels that are "in view", always up-to-date - make_shared(CHANNEL_FLAG_MAXFAMILYCLIENTS_UNLIMITED, "CHANNEL_FLAG_MAXFAMILYCLIENTS_UNLIMITED", "1", TYPE_BOOL, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE),//Available for all channels that are "in view", always up-to-date - make_shared(CHANNEL_FLAG_MAXFAMILYCLIENTS_INHERITED, "CHANNEL_FLAG_MAXFAMILYCLIENTS_INHERITED", "0", TYPE_BOOL, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE),//Available for all channels that are "in view", always up-to-date - make_shared(CHANNEL_FLAG_ARE_SUBSCRIBED, "CHANNEL_FLAG_ARE_SUBSCRIBED", "1", TYPE_BOOL, FLAG_INTERNAL), //Only available manager side, stores whether we are subscribed to this channel - make_shared(CHANNEL_FILEPATH, "CHANNEL_FILEPATH", "", TYPE_STRING, FLAG_SS), //not available manager side, the folder used for file-transfers for this channel - make_shared(CHANNEL_NEEDED_TALK_POWER, "CHANNEL_NEEDED_TALK_POWER", "0", TYPE_UNSIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //Available for all channels that are "in view", always up-to-date - make_shared(CHANNEL_FORCED_SILENCE, "CHANNEL_FORCED_SILENCE", "0", TYPE_BOOL, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //Available for all channels that are "in view", always up-to-date - make_shared(CHANNEL_NAME_PHONETIC, "CHANNEL_NAME_PHONETIC", "", TYPE_STRING, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //Available for all channels that are "in view", always up-to-date - make_shared(CHANNEL_ICON_ID, "CHANNEL_ICON_ID", "0", TYPE_UNSIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //Available for all channels that are "in view", always up-to-date - make_shared(CHANNEL_FLAG_PRIVATE, "CHANNEL_FLAG_PRIVATE", "0", TYPE_BOOL, FLAG_CHANNEL_VIEW | FLAG_SS), //Available for all channels that are "in view", always up-to-date - make_shared(CHANNEL_LAST_LEFT, "CHANNEL_LAST_LEFT", "0", TYPE_UNSIGNED_NUMBER, FLAG_SAVE | FLAG_CHANNEL_VIEW | FLAG_CHANNEL_VARIABLE | FLAG_NEW), //Available for all channels that are "in view", always up-to-date - make_shared(CHANNEL_CREATED_AT, "CHANNEL_CREATED_AT", "0", TYPE_UNSIGNED_NUMBER, FLAG_SS | FLAG_CHANNEL_VIEW | FLAG_CHANNEL_VARIABLE | FLAG_NEW), //Available for all channels that are "in view", always up-to-date - make_shared(CHANNEL_CREATED_BY, "CHANNEL_CREATED_BY", "0", TYPE_UNSIGNED_NUMBER, FLAG_SS | FLAG_CHANNEL_VIEW | FLAG_CHANNEL_VARIABLE | FLAG_NEW), //Available for all channels that are "in view", always up-to-date - make_shared(CHANNEL_CONVERSATION_HISTORY_LENGTH, "CHANNEL_CONVERSATION_HISTORY_LENGTH", "1500", TYPE_SIGNED_NUMBER, FLAG_SS | FLAG_CHANNEL_VIEW | FLAG_CHANNEL_VARIABLE | FLAG_NEW | FLAG_USER_EDITABLE), - make_shared(CHANNEL_FLAG_CONVERSATION_PRIVATE, "CHANNEL_FLAG_CONVERSATION_PRIVATE", "0", TYPE_BOOL, FLAG_SS | FLAG_CHANNEL_VIEW | FLAG_CHANNEL_VARIABLE | FLAG_NEW | FLAG_USER_EDITABLE) - }; + array, ChannelProperties::CHANNEL_ENDMARKER> channel_info = { + make_shared(CHANNEL_UNDEFINED, "CHANNEL_UNDEFINED", "", TYPE_UNKNOWN, 0), //Must be at index 0! + make_shared(CHANNEL_ID, "cid", "0", TYPE_UNSIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS), + make_shared(CHANNEL_PID, "cpid", "0", TYPE_UNSIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS), + make_shared(CHANNEL_NAME, "CHANNEL_NAME", "undefined", TYPE_STRING, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //Available for all channels that are "in view", always up-to-date + make_shared(CHANNEL_TOPIC, "CHANNEL_TOPIC", "", TYPE_STRING, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //Available for all channels that are "in view", always up-to-date + make_shared(CHANNEL_DESCRIPTION, "CHANNEL_DESCRIPTION", "", TYPE_STRING, FLAG_CHANNEL_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE), //Must be requested (=> requestChannelDescription) + make_shared(CHANNEL_PASSWORD, "CHANNEL_PASSWORD", "0", TYPE_STRING, FLAG_SS | FLAG_USER_EDITABLE), //not available manager side + make_shared(CHANNEL_CODEC, "CHANNEL_CODEC", "4", TYPE_UNSIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //Available for all channels that are "in view", always up-to-date + make_shared(CHANNEL_CODEC_QUALITY, "CHANNEL_CODEC_QUALITY", "7", TYPE_UNSIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //Available for all channels that are "in view", always up-to-date + make_shared(CHANNEL_MAXCLIENTS, "CHANNEL_MAXCLIENTS", "-1", TYPE_SIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //Available for all channels that are "in view", always up-to-date + make_shared(CHANNEL_MAXFAMILYCLIENTS, "CHANNEL_MAXFAMILYCLIENTS", "-1", TYPE_SIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //Available for all channels that are "in view", always up-to-date + make_shared(CHANNEL_ORDER, "CHANNEL_ORDER", "0", TYPE_UNSIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //Available for all channels that are "in view", always up-to-date + make_shared(CHANNEL_FLAG_PERMANENT, "CHANNEL_FLAG_PERMANENT", "1", TYPE_BOOL, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //Available for all channels that are "in view", always up-to-date + make_shared(CHANNEL_FLAG_SEMI_PERMANENT, "CHANNEL_FLAG_SEMI_PERMANENT", "0", TYPE_BOOL, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //Available for all channels that are "in view", always up-to-date + make_shared(CHANNEL_FLAG_DEFAULT, "CHANNEL_FLAG_DEFAULT", "0", TYPE_BOOL, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //Available for all channels that are "in view", always up-to-date + make_shared(CHANNEL_FLAG_PASSWORD, "CHANNEL_FLAG_PASSWORD", "0", TYPE_BOOL, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //Available for all channels that are "in view", always up-to-date + make_shared(CHANNEL_CODEC_LATENCY_FACTOR, "CHANNEL_CODEC_LATENCY_FACTOR", "1", TYPE_UNSIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //Available for all channels that are "in view", always up-to-date + make_shared(CHANNEL_CODEC_IS_UNENCRYPTED, "CHANNEL_CODEC_IS_UNENCRYPTED", "1", TYPE_BOOL, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //Available for all channels that are "in view", always up-to-date + make_shared(CHANNEL_SECURITY_SALT, "CHANNEL_SECURITY_SALT", "", TYPE_STRING, FLAG_SS), //Not available manager side, not used in teamspeak, only SDK. Sets the options+salt for security hash. + make_shared(CHANNEL_DELETE_DELAY, "CHANNEL_DELETE_DELAY", "0", TYPE_UNSIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //How many seconds to wait before deleting this channel + make_shared(CHANNEL_FLAG_MAXCLIENTS_UNLIMITED, "CHANNEL_FLAG_MAXCLIENTS_UNLIMITED", "1", TYPE_BOOL, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //Available for all channels that are "in view", always up-to-date + make_shared(CHANNEL_FLAG_MAXFAMILYCLIENTS_UNLIMITED, "CHANNEL_FLAG_MAXFAMILYCLIENTS_UNLIMITED", "1", TYPE_BOOL, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE),//Available for all channels that are "in view", always up-to-date + make_shared(CHANNEL_FLAG_MAXFAMILYCLIENTS_INHERITED, "CHANNEL_FLAG_MAXFAMILYCLIENTS_INHERITED", "0", TYPE_BOOL, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE),//Available for all channels that are "in view", always up-to-date + make_shared(CHANNEL_FLAG_ARE_SUBSCRIBED, "CHANNEL_FLAG_ARE_SUBSCRIBED", "1", TYPE_BOOL, FLAG_INTERNAL), //Only available manager side, stores whether we are subscribed to this channel + make_shared(CHANNEL_FILEPATH, "CHANNEL_FILEPATH", "", TYPE_STRING, FLAG_SS), //not available manager side, the folder used for file-transfers for this channel + make_shared(CHANNEL_NEEDED_TALK_POWER, "CHANNEL_NEEDED_TALK_POWER", "0", TYPE_UNSIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //Available for all channels that are "in view", always up-to-date + make_shared(CHANNEL_FORCED_SILENCE, "CHANNEL_FORCED_SILENCE", "0", TYPE_BOOL, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //Available for all channels that are "in view", always up-to-date + make_shared(CHANNEL_NAME_PHONETIC, "CHANNEL_NAME_PHONETIC", "", TYPE_STRING, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //Available for all channels that are "in view", always up-to-date + make_shared(CHANNEL_ICON_ID, "CHANNEL_ICON_ID", "0", TYPE_UNSIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //Available for all channels that are "in view", always up-to-date + make_shared(CHANNEL_FLAG_PRIVATE, "CHANNEL_FLAG_PRIVATE", "0", TYPE_BOOL, FLAG_CHANNEL_VIEW | FLAG_SS), //Available for all channels that are "in view", always up-to-date + make_shared(CHANNEL_LAST_LEFT, "CHANNEL_LAST_LEFT", "0", TYPE_UNSIGNED_NUMBER, FLAG_SAVE | FLAG_CHANNEL_VIEW | FLAG_CHANNEL_VARIABLE | FLAG_NEW), //Available for all channels that are "in view", always up-to-date + make_shared(CHANNEL_CREATED_AT, "CHANNEL_CREATED_AT", "0", TYPE_UNSIGNED_NUMBER, FLAG_SS | FLAG_CHANNEL_VIEW | FLAG_CHANNEL_VARIABLE | FLAG_NEW), //Available for all channels that are "in view", always up-to-date + make_shared(CHANNEL_CREATED_BY, "CHANNEL_CREATED_BY", "0", TYPE_UNSIGNED_NUMBER, FLAG_SS | FLAG_CHANNEL_VIEW | FLAG_CHANNEL_VARIABLE | FLAG_NEW), //Available for all channels that are "in view", always up-to-date + make_shared(CHANNEL_CONVERSATION_HISTORY_LENGTH, "CHANNEL_CONVERSATION_HISTORY_LENGTH", "1500", TYPE_SIGNED_NUMBER, FLAG_SS | FLAG_CHANNEL_VIEW | FLAG_CHANNEL_VARIABLE | FLAG_NEW | FLAG_USER_EDITABLE), + make_shared(CHANNEL_FLAG_CONVERSATION_PRIVATE, "CHANNEL_FLAG_CONVERSATION_PRIVATE", "0", TYPE_BOOL, FLAG_SS | FLAG_CHANNEL_VIEW | FLAG_CHANNEL_VARIABLE | FLAG_NEW | FLAG_USER_EDITABLE) + }; - array, GroupProperties::GROUP_ENDMARKER> group_info = { - make_shared(GROUP_UNDEFINED, "GROUP_UNDEFINED", "", TYPE_UNKNOWN, 0), - make_shared(GROUP_ID, "gid", "0", TYPE_UNSIGNED_NUMBER, FLAG_INTERNAL), - make_shared(GROUP_TYPE, "type", "0", TYPE_UNSIGNED_NUMBER, FLAG_GROUP_VIEW), - make_shared(GROUP_NAME, "name", "Undefined group", TYPE_STRING, FLAG_GROUP_VIEW), - make_shared(GROUP_SORTID, "sortid", "0", TYPE_UNSIGNED_NUMBER, FLAG_GROUP_VIEW), - make_shared(GROUP_SAVEDB, "savedb", "0", TYPE_BOOL, FLAG_GROUP_VIEW), - make_shared(GROUP_NAMEMODE, "namemode", "0", TYPE_UNSIGNED_NUMBER, FLAG_GROUP_VIEW), - make_shared(GROUP_ICONID, "iconid", "0", TYPE_UNSIGNED_NUMBER, FLAG_GROUP_VIEW) - }; + array, GroupProperties::GROUP_ENDMARKER> group_info = { + make_shared(GROUP_UNDEFINED, "GROUP_UNDEFINED", "", TYPE_UNKNOWN, 0), + make_shared(GROUP_ID, "gid", "0", TYPE_UNSIGNED_NUMBER, FLAG_INTERNAL), + make_shared(GROUP_TYPE, "type", "0", TYPE_UNSIGNED_NUMBER, FLAG_GROUP_VIEW), + make_shared(GROUP_NAME, "name", "Undefined group", TYPE_STRING, FLAG_GROUP_VIEW), + make_shared(GROUP_SORTID, "sortid", "0", TYPE_UNSIGNED_NUMBER, FLAG_GROUP_VIEW), + make_shared(GROUP_SAVEDB, "savedb", "0", TYPE_BOOL, FLAG_GROUP_VIEW), + make_shared(GROUP_NAMEMODE, "namemode", "0", TYPE_UNSIGNED_NUMBER, FLAG_GROUP_VIEW), + make_shared(GROUP_ICONID, "iconid", "0", TYPE_UNSIGNED_NUMBER, FLAG_GROUP_VIEW) + }; - array, ClientProperties::CLIENT_ENDMARKER> client_info = { - make_shared(CLIENT_UNDEFINED, "CLIENT_UNDEFINED", "undefined", TYPE_UNKNOWN, 0), - make_shared(CLIENT_UNIQUE_IDENTIFIER, "CLIENT_UNIQUE_IDENTIFIER", "", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_SNAPSHOT | FLAG_GLOBAL), //automatically up-to-date for any manager "in view", can be used to identify this particular manager installation - make_shared(CLIENT_NICKNAME, "CLIENT_NICKNAME", "undefined", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_SAVE_MUSIC | FLAG_SNAPSHOT | FLAG_GLOBAL | FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view" - make_shared(CLIENT_VERSION, "CLIENT_VERSION", "unknown", TYPE_STRING, FLAG_CLIENT_VVSS | FLAG_USER_EDITABLE | FLAG_GLOBAL | FLAG_SAVE_MUSIC), //for other clients than ourself, this needs to be requested (=> requestClientVariables) - make_shared(CLIENT_PLATFORM, "CLIENT_PLATFORM", "unknown", TYPE_STRING, FLAG_CLIENT_VVSS | FLAG_USER_EDITABLE | FLAG_GLOBAL | FLAG_SAVE_MUSIC), //for other clients than ourself, this needs to be requested (=> requestClientVariables) - make_shared(CLIENT_FLAG_TALKING, "CLIENT_FLAG_TALKING", "0", TYPE_BOOL, FLAG_INTERNAL), //automatically up-to-date for any manager that can be heard (in room / whisper) - make_shared(CLIENT_INPUT_MUTED, "CLIENT_INPUT_MUTED", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view", this clients microphone mute status - make_shared(CLIENT_OUTPUT_MUTED, "CLIENT_OUTPUT_MUTED", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view", this clients headphones/speakers/mic combined mute status - make_shared(CLIENT_OUTPUTONLY_MUTED, "CLIENT_OUTPUTONLY_MUTED", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view", this clients headphones/speakers only mute status - make_shared(CLIENT_INPUT_HARDWARE, "CLIENT_INPUT_HARDWARE", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view", this clients microphone hardware status (is the capture device opened?) - make_shared(CLIENT_OUTPUT_HARDWARE, "CLIENT_OUTPUT_HARDWARE", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view", this clients headphone/speakers hardware status (is the playback device opened?) - make_shared(CLIENT_DEFAULT_CHANNEL, "CLIENT_DEFAULT_CHANNEL", "", TYPE_STRING, FLAG_INTERNAL), //only usable for ourself, the default channel we used to connect on our last connection attempt - make_shared(CLIENT_DEFAULT_CHANNEL_PASSWORD, "CLIENT_DEFAULT_CHANNEL_PASSWORD", "", TYPE_STRING, FLAG_INTERNAL), //internal use - make_shared(CLIENT_SERVER_PASSWORD, "CLIENT_SERVER_PASSWORD", "", TYPE_STRING, FLAG_INTERNAL), //internal use - make_shared(CLIENT_META_DATA, "CLIENT_META_DATA", "", TYPE_STRING, FLAG_CLIENT_VIEW| FLAG_GLOBAL|FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view", not used by TeamSpeak, free storage for sdk users - make_shared(CLIENT_IS_RECORDING, "CLIENT_IS_RECORDING", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view" - make_shared(CLIENT_VERSION_SIGN, "CLIENT_VERSION_SIGN", "", TYPE_STRING, FLAG_INTERNAL), //sign - make_shared(CLIENT_SECURITY_HASH, "CLIENT_SECURITY_HASH", "", TYPE_STRING, FLAG_INTERNAL), //SDK use, not used by teamspeak. Hash is provided by an outside source. A channel will use the security salt + other manager data to calculate a hash, which must be the same as the one provided here. + array, ClientProperties::CLIENT_ENDMARKER> client_info = { + make_shared(CLIENT_UNDEFINED, "CLIENT_UNDEFINED", "undefined", TYPE_UNKNOWN, 0), + make_shared(CLIENT_UNIQUE_IDENTIFIER, "CLIENT_UNIQUE_IDENTIFIER", "", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_SNAPSHOT | FLAG_GLOBAL), //automatically up-to-date for any manager "in view", can be used to identify this particular manager installation + make_shared(CLIENT_NICKNAME, "CLIENT_NICKNAME", "undefined", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_SAVE_MUSIC | FLAG_SNAPSHOT | FLAG_GLOBAL | FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view" + make_shared(CLIENT_VERSION, "CLIENT_VERSION", "unknown", TYPE_STRING, FLAG_CLIENT_VVSS | FLAG_USER_EDITABLE | FLAG_GLOBAL | FLAG_SAVE_MUSIC), //for other clients than ourself, this needs to be requested (=> requestClientVariables) + make_shared(CLIENT_PLATFORM, "CLIENT_PLATFORM", "unknown", TYPE_STRING, FLAG_CLIENT_VVSS | FLAG_USER_EDITABLE | FLAG_GLOBAL | FLAG_SAVE_MUSIC), //for other clients than ourself, this needs to be requested (=> requestClientVariables) + make_shared(CLIENT_FLAG_TALKING, "CLIENT_FLAG_TALKING", "0", TYPE_BOOL, FLAG_INTERNAL), //automatically up-to-date for any manager that can be heard (in room / whisper) + make_shared(CLIENT_INPUT_MUTED, "CLIENT_INPUT_MUTED", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view", this clients microphone mute status + make_shared(CLIENT_OUTPUT_MUTED, "CLIENT_OUTPUT_MUTED", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view", this clients headphones/speakers/mic combined mute status + make_shared(CLIENT_OUTPUTONLY_MUTED, "CLIENT_OUTPUTONLY_MUTED", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view", this clients headphones/speakers only mute status + make_shared(CLIENT_INPUT_HARDWARE, "CLIENT_INPUT_HARDWARE", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view", this clients microphone hardware status (is the capture device opened?) + make_shared(CLIENT_OUTPUT_HARDWARE, "CLIENT_OUTPUT_HARDWARE", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view", this clients headphone/speakers hardware status (is the playback device opened?) + make_shared(CLIENT_DEFAULT_CHANNEL, "CLIENT_DEFAULT_CHANNEL", "", TYPE_STRING, FLAG_INTERNAL), //only usable for ourself, the default channel we used to connect on our last connection attempt + make_shared(CLIENT_DEFAULT_CHANNEL_PASSWORD, "CLIENT_DEFAULT_CHANNEL_PASSWORD", "", TYPE_STRING, FLAG_INTERNAL), //internal use + make_shared(CLIENT_SERVER_PASSWORD, "CLIENT_SERVER_PASSWORD", "", TYPE_STRING, FLAG_INTERNAL), //internal use + make_shared(CLIENT_META_DATA, "CLIENT_META_DATA", "", TYPE_STRING, FLAG_CLIENT_VIEW| FLAG_GLOBAL|FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view", not used by TeamSpeak, free storage for sdk users + make_shared(CLIENT_IS_RECORDING, "CLIENT_IS_RECORDING", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view" + make_shared(CLIENT_VERSION_SIGN, "CLIENT_VERSION_SIGN", "", TYPE_STRING, FLAG_INTERNAL), //sign + make_shared(CLIENT_SECURITY_HASH, "CLIENT_SECURITY_HASH", "", TYPE_STRING, FLAG_INTERNAL), //SDK use, not used by teamspeak. Hash is provided by an outside source. A channel will use the security salt + other manager data to calculate a hash, which must be the same as the one provided here. - //Rare properties - make_shared(CLIENT_KEY_OFFSET, "CLIENT_KEY_OFFSET", "0", TYPE_UNSIGNED_NUMBER, FLAG_INTERNAL), //internal use - make_shared(CLIENT_LOGIN_NAME, "CLIENT_LOGIN_NAME", "", TYPE_STRING, FLAG_CLIENT_VARIABLE| FLAG_GLOBAL), //used for serverquery clients, makes no sense on normal clients currently - make_shared(CLIENT_LOGIN_PASSWORD, "CLIENT_LOGIN_PASSWORD", "", TYPE_STRING, FLAG_INTERNAL| FLAG_GLOBAL), //used for serverquery clients, makes no sense on normal clients currently - make_shared(CLIENT_DATABASE_ID, "CLIENT_DATABASE_ID", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VIEW | FLAG_GLOBAL), //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, holds database manager id - make_shared(CLIENT_ID, "clid", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VV), //clid! - make_shared(CLIENT_HARDWARE_ID, "hwid", "", TYPE_STRING, FLAG_SAVE), //hwid! - make_shared(CLIENT_CHANNEL_GROUP_ID, "CLIENT_CHANNEL_GROUP_ID", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VIEW), //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, holds database manager id - make_shared(CLIENT_SERVERGROUPS, "CLIENT_SERVERGROUPS", "0", TYPE_STRING, FLAG_CLIENT_VIEW), //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, holds all servergroups manager belongs too - make_shared(CLIENT_CREATED, "CLIENT_CREATED", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VARIABLE | FLAG_SAVE_MUSIC | FLAG_SNAPSHOT | FLAG_GLOBAL), //this needs to be requested (=> requestClientVariables), first time this manager connected to this server - make_shared(CLIENT_LASTCONNECTED, "CLIENT_LASTCONNECTED", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VARIABLE | FLAG_SNAPSHOT | FLAG_GLOBAL), //this needs to be requested (=> requestClientVariables), last time this manager connected to this server - make_shared(CLIENT_TOTALCONNECTIONS, "CLIENT_TOTALCONNECTIONS", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VARIABLE | FLAG_CLIENT_VIEW | FLAG_SNAPSHOT | FLAG_GLOBAL), //this needs to be requested (=> requestClientVariables), how many times this manager connected to this server - make_shared(CLIENT_AWAY, "CLIENT_AWAY", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view", this clients away status - make_shared(CLIENT_AWAY_MESSAGE, "CLIENT_AWAY_MESSAGE", "", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view", this clients away message - make_shared(CLIENT_TYPE, "CLIENT_TYPE", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VIEW | FLAG_GLOBAL), //automatically up-to-date for any manager "in view", determines if this is a real manager or a server-query connection - make_shared(CLIENT_TYPE_EXACT, "CLIENT_TYPE_EXACT", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VIEW | FLAG_NEW | FLAG_GLOBAL), //automatically up-to-date for any manager "in view", determines if this is a real manager or a server-query connection - make_shared(CLIENT_FLAG_AVATAR, "CLIENT_FLAG_AVATAR", "", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_SAVE | FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view", this manager got an avatar - make_shared(CLIENT_TALK_POWER, "CLIENT_TALK_POWER", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VIEW), //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, holds database manager id - make_shared(CLIENT_TALK_REQUEST, "CLIENT_TALK_REQUEST", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, holds timestamp where manager requested to talk - make_shared(CLIENT_TALK_REQUEST_MSG, "CLIENT_TALK_REQUEST_MSG", "", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, holds matter for the request - make_shared(CLIENT_DESCRIPTION, "CLIENT_DESCRIPTION", "", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view" - make_shared(CLIENT_IS_TALKER, "CLIENT_IS_TALKER", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view" - make_shared(CLIENT_MONTH_BYTES_UPLOADED, "CLIENT_MONTH_BYTES_UPLOADED", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VARIABLE | FLAG_SAVE), //this needs to be requested (=> requestClientVariables) - make_shared(CLIENT_MONTH_BYTES_DOWNLOADED, "CLIENT_MONTH_BYTES_DOWNLOADED", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VARIABLE | FLAG_SAVE), //this needs to be requested (=> requestClientVariables) - make_shared(CLIENT_TOTAL_BYTES_UPLOADED, "CLIENT_TOTAL_BYTES_UPLOADED", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VARIABLE | FLAG_SAVE), //this needs to be requested (=> requestClientVariables) - make_shared(CLIENT_TOTAL_BYTES_DOWNLOADED, "CLIENT_TOTAL_BYTES_DOWNLOADED", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VARIABLE | FLAG_SAVE), //this needs to be requested (=> requestClientVariables) - make_shared(CLIENT_TOTAL_ONLINE_TIME, "CLIENT_TOTAL_ONLINE_TIME", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VARIABLE | FLAG_SAVE | FLAG_NEW), //this needs to be requested (=> requestClientVariables) - make_shared(CLIENT_MONTH_ONLINE_TIME, "CLIENT_MONTH_ONLINE_TIME", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VARIABLE | FLAG_SAVE | FLAG_NEW), //this needs to be requested (=> requestClientVariables) - make_shared(CLIENT_IS_PRIORITY_SPEAKER, "CLIENT_IS_PRIORITY_SPEAKER", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view" - make_shared(CLIENT_UNREAD_MESSAGES, "CLIENT_UNREAD_MESSAGES", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VIEW), //automatically up-to-date for any manager "in view" - make_shared(CLIENT_NICKNAME_PHONETIC, "CLIENT_NICKNAME_PHONETIC", "", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view" - make_shared(CLIENT_NEEDED_SERVERQUERY_VIEW_POWER, "CLIENT_NEEDED_SERVERQUERY_VIEW_POWER", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VIEW), //automatically up-to-date for any manager "in view" - make_shared(CLIENT_DEFAULT_TOKEN, "CLIENT_DEFAULT_TOKEN", "", TYPE_STRING, FLAG_INTERNAL), //only usable for ourself, the default token we used to connect on our last connection attempt - make_shared(CLIENT_ICON_ID, "CLIENT_ICON_ID", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VIEW | FLAG_CLIENT_VARIABLE), //automatically up-to-date for any manager "in view" - make_shared(CLIENT_IS_CHANNEL_COMMANDER, "CLIENT_IS_CHANNEL_COMMANDER", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE | FLAG_SAVE_MUSIC), //automatically up-to-date for any manager "in view" - make_shared(CLIENT_COUNTRY, "CLIENT_COUNTRY", "TS", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_CLIENT_VARIABLE | FLAG_GLOBAL | FLAG_SAVE_MUSIC | FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view" - make_shared(CLIENT_CHANNEL_GROUP_INHERITED_CHANNEL_ID, "CLIENT_CHANNEL_GROUP_INHERITED_CHANNEL_ID", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VIEW), //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, contains channel_id where the channel_group_id is set from - make_shared(CLIENT_BADGES, "CLIENT_BADGES", "", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view", stores icons for partner badges - make_shared(CLIENT_MYTEAMSPEAK_ID, "CLIENT_MYTEAMSPEAK_ID", "", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view", stores icons for partner badges - make_shared(CLIENT_INTEGRATIONS, "CLIENT_INTEGRATIONS", "", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view", stores icons for partner badges - make_shared(CLIENT_ACTIVE_INTEGRATIONS_INFO, "CLIENT_ACTIVE_INTEGRATIONS_INFO", "", TYPE_STRING, FLAG_INTERNAL | FLAG_USER_EDITABLE), + //Rare properties + make_shared(CLIENT_KEY_OFFSET, "CLIENT_KEY_OFFSET", "0", TYPE_UNSIGNED_NUMBER, FLAG_INTERNAL), //internal use + make_shared(CLIENT_LOGIN_NAME, "CLIENT_LOGIN_NAME", "", TYPE_STRING, FLAG_CLIENT_VARIABLE| FLAG_GLOBAL), //used for serverquery clients, makes no sense on normal clients currently + make_shared(CLIENT_LOGIN_PASSWORD, "CLIENT_LOGIN_PASSWORD", "", TYPE_STRING, FLAG_INTERNAL| FLAG_GLOBAL), //used for serverquery clients, makes no sense on normal clients currently + make_shared(CLIENT_DATABASE_ID, "CLIENT_DATABASE_ID", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VIEW | FLAG_GLOBAL), //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, holds database manager id + make_shared(CLIENT_ID, "clid", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VV), //clid! + make_shared(CLIENT_HARDWARE_ID, "hwid", "", TYPE_STRING, FLAG_SAVE), //hwid! + make_shared(CLIENT_CHANNEL_GROUP_ID, "CLIENT_CHANNEL_GROUP_ID", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VIEW), //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, holds database manager id + make_shared(CLIENT_SERVERGROUPS, "CLIENT_SERVERGROUPS", "0", TYPE_STRING, FLAG_CLIENT_VIEW), //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, holds all servergroups manager belongs too + make_shared(CLIENT_CREATED, "CLIENT_CREATED", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VARIABLE | FLAG_SAVE_MUSIC | FLAG_SNAPSHOT | FLAG_GLOBAL), //this needs to be requested (=> requestClientVariables), first time this manager connected to this server + make_shared(CLIENT_LASTCONNECTED, "CLIENT_LASTCONNECTED", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VARIABLE | FLAG_SNAPSHOT | FLAG_GLOBAL), //this needs to be requested (=> requestClientVariables), last time this manager connected to this server + make_shared(CLIENT_TOTALCONNECTIONS, "CLIENT_TOTALCONNECTIONS", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VARIABLE | FLAG_CLIENT_VIEW | FLAG_SNAPSHOT | FLAG_GLOBAL), //this needs to be requested (=> requestClientVariables), how many times this manager connected to this server + make_shared(CLIENT_AWAY, "CLIENT_AWAY", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view", this clients away status + make_shared(CLIENT_AWAY_MESSAGE, "CLIENT_AWAY_MESSAGE", "", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view", this clients away message + make_shared(CLIENT_TYPE, "CLIENT_TYPE", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VIEW | FLAG_GLOBAL), //automatically up-to-date for any manager "in view", determines if this is a real manager or a server-query connection + make_shared(CLIENT_TYPE_EXACT, "CLIENT_TYPE_EXACT", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VIEW | FLAG_NEW | FLAG_GLOBAL), //automatically up-to-date for any manager "in view", determines if this is a real manager or a server-query connection + make_shared(CLIENT_FLAG_AVATAR, "CLIENT_FLAG_AVATAR", "", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_SAVE | FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view", this manager got an avatar + make_shared(CLIENT_TALK_POWER, "CLIENT_TALK_POWER", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VIEW), //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, holds database manager id + make_shared(CLIENT_TALK_REQUEST, "CLIENT_TALK_REQUEST", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, holds timestamp where manager requested to talk + make_shared(CLIENT_TALK_REQUEST_MSG, "CLIENT_TALK_REQUEST_MSG", "", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, holds matter for the request + make_shared(CLIENT_DESCRIPTION, "CLIENT_DESCRIPTION", "", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view" + make_shared(CLIENT_IS_TALKER, "CLIENT_IS_TALKER", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view" + make_shared(CLIENT_MONTH_BYTES_UPLOADED, "CLIENT_MONTH_BYTES_UPLOADED", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VARIABLE | FLAG_SAVE), //this needs to be requested (=> requestClientVariables) + make_shared(CLIENT_MONTH_BYTES_DOWNLOADED, "CLIENT_MONTH_BYTES_DOWNLOADED", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VARIABLE | FLAG_SAVE), //this needs to be requested (=> requestClientVariables) + make_shared(CLIENT_TOTAL_BYTES_UPLOADED, "CLIENT_TOTAL_BYTES_UPLOADED", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VARIABLE | FLAG_SAVE), //this needs to be requested (=> requestClientVariables) + make_shared(CLIENT_TOTAL_BYTES_DOWNLOADED, "CLIENT_TOTAL_BYTES_DOWNLOADED", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VARIABLE | FLAG_SAVE), //this needs to be requested (=> requestClientVariables) + make_shared(CLIENT_TOTAL_ONLINE_TIME, "CLIENT_TOTAL_ONLINE_TIME", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VARIABLE | FLAG_SAVE | FLAG_NEW), //this needs to be requested (=> requestClientVariables) + make_shared(CLIENT_MONTH_ONLINE_TIME, "CLIENT_MONTH_ONLINE_TIME", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VARIABLE | FLAG_SAVE | FLAG_NEW), //this needs to be requested (=> requestClientVariables) + make_shared(CLIENT_IS_PRIORITY_SPEAKER, "CLIENT_IS_PRIORITY_SPEAKER", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view" + make_shared(CLIENT_UNREAD_MESSAGES, "CLIENT_UNREAD_MESSAGES", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VIEW), //automatically up-to-date for any manager "in view" + make_shared(CLIENT_NICKNAME_PHONETIC, "CLIENT_NICKNAME_PHONETIC", "", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view" + make_shared(CLIENT_NEEDED_SERVERQUERY_VIEW_POWER, "CLIENT_NEEDED_SERVERQUERY_VIEW_POWER", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VIEW), //automatically up-to-date for any manager "in view" + make_shared(CLIENT_DEFAULT_TOKEN, "CLIENT_DEFAULT_TOKEN", "", TYPE_STRING, FLAG_INTERNAL), //only usable for ourself, the default token we used to connect on our last connection attempt + make_shared(CLIENT_ICON_ID, "CLIENT_ICON_ID", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VIEW | FLAG_CLIENT_VARIABLE), //automatically up-to-date for any manager "in view" + make_shared(CLIENT_IS_CHANNEL_COMMANDER, "CLIENT_IS_CHANNEL_COMMANDER", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE | FLAG_SAVE_MUSIC), //automatically up-to-date for any manager "in view" + make_shared(CLIENT_COUNTRY, "CLIENT_COUNTRY", "TS", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_CLIENT_VARIABLE | FLAG_GLOBAL | FLAG_SAVE_MUSIC | FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view" + make_shared(CLIENT_CHANNEL_GROUP_INHERITED_CHANNEL_ID, "CLIENT_CHANNEL_GROUP_INHERITED_CHANNEL_ID", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VIEW), //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, contains channel_id where the channel_group_id is set from + make_shared(CLIENT_BADGES, "CLIENT_BADGES", "", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view", stores icons for partner badges + make_shared(CLIENT_MYTEAMSPEAK_ID, "CLIENT_MYTEAMSPEAK_ID", "", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_SS | FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view", stores icons for partner badges + make_shared(CLIENT_INTEGRATIONS, "CLIENT_INTEGRATIONS", "", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE), //automatically up-to-date for any manager "in view", stores icons for partner badges + make_shared(CLIENT_ACTIVE_INTEGRATIONS_INFO, "CLIENT_ACTIVE_INTEGRATIONS_INFO", "", TYPE_STRING, FLAG_INTERNAL | FLAG_USER_EDITABLE), - //Using FLAG_GLOBAL here,lse they will be overridden on clientinit - make_shared(CLIENT_TEAFORO_ID, "CLIENT_TEAFORO_ID", "0", TYPE_UNSIGNED_NUMBER, FLAG_NEW | FLAG_CLIENT_VIEW | FLAG_GLOBAL), - make_shared(CLIENT_TEAFORO_NAME, "CLIENT_TEAFORO_NAME", "", TYPE_STRING, FLAG_NEW | FLAG_CLIENT_VIEW | FLAG_GLOBAL), - make_shared(CLIENT_TEAFORO_FLAGS, "CLIENT_TEAFORO_FLAGS", "0", TYPE_UNSIGNED_NUMBER, FLAG_NEW | FLAG_CLIENT_VIEW | FLAG_GLOBAL), + //Using FLAG_GLOBAL here,lse they will be overridden on clientinit + make_shared(CLIENT_TEAFORO_ID, "CLIENT_TEAFORO_ID", "0", TYPE_UNSIGNED_NUMBER, FLAG_NEW | FLAG_CLIENT_VIEW | FLAG_GLOBAL), + make_shared(CLIENT_TEAFORO_NAME, "CLIENT_TEAFORO_NAME", "", TYPE_STRING, FLAG_NEW | FLAG_CLIENT_VIEW | FLAG_GLOBAL), + make_shared(CLIENT_TEAFORO_FLAGS, "CLIENT_TEAFORO_FLAGS", "0", TYPE_UNSIGNED_NUMBER, FLAG_NEW | FLAG_CLIENT_VIEW | FLAG_GLOBAL), - //Music bot stuff - make_shared(CLIENT_OWNER, "CLIENT_OWNER", "0", TYPE_UNSIGNED_NUMBER, FLAG_NEW | FLAG_CLIENT_VIEW), - make_shared(CLIENT_BOT_TYPE, "CLIENT_BOT_TYPE", "0", TYPE_UNSIGNED_NUMBER, FLAG_NEW | FLAG_SAVE_MUSIC | FLAG_USER_EDITABLE | FLAG_CLIENT_VIEW), - make_shared(CLIENT_LAST_CHANNEL, "CLIENT_LAST_CHANNEL", "0", TYPE_UNSIGNED_NUMBER, FLAG_NEW | FLAG_INTERNAL | FLAG_SAVE_MUSIC), - make_shared(CLIENT_PLAYER_STATE, "PLAYER_STATE", "0", TYPE_UNSIGNED_NUMBER, FLAG_NEW | FLAG_CLIENT_VIEW | FLAG_SAVE_MUSIC), - make_shared(CLIENT_PLAYER_VOLUME, "PLAYER_VOLUME", "1", TYPE_FLOAT, FLAG_NEW | FLAG_SAVE_MUSIC | FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE), - make_shared(CLIENT_PLAYLIST_ID, "CLIENT_PLAYLIST_ID", "0", TYPE_UNSIGNED_NUMBER, FLAG_NEW | FLAG_CLIENT_VARIABLE | FLAG_SAVE_MUSIC), - make_shared(CLIENT_DISABLED, "CLIENT_DISABLED", "0", TYPE_BOOL, FLAG_NEW | FLAG_CLIENT_VARIABLE), - make_shared(CLIENT_UPTIME_MODE, "CLIENT_UPTIME_MODE", "0", TYPE_UNSIGNED_NUMBER, FLAG_NEW | FLAG_CLIENT_VARIABLE | FLAG_USER_EDITABLE | FLAG_SAVE_MUSIC), - make_shared(CLIENT_FLAG_NOTIFY_SONG_CHANGE, "CLIENT_FLAG_NOTIFY_SONG_CHANGE", "1", TYPE_BOOL, FLAG_NEW | FLAG_CLIENT_VARIABLE | FLAG_USER_EDITABLE | FLAG_SAVE_MUSIC) - }; + //Music bot stuff + make_shared(CLIENT_OWNER, "CLIENT_OWNER", "0", TYPE_UNSIGNED_NUMBER, FLAG_NEW | FLAG_CLIENT_VIEW), + make_shared(CLIENT_BOT_TYPE, "CLIENT_BOT_TYPE", "0", TYPE_UNSIGNED_NUMBER, FLAG_NEW | FLAG_SAVE_MUSIC | FLAG_USER_EDITABLE | FLAG_CLIENT_VIEW), + make_shared(CLIENT_LAST_CHANNEL, "CLIENT_LAST_CHANNEL", "0", TYPE_UNSIGNED_NUMBER, FLAG_NEW | FLAG_INTERNAL | FLAG_SAVE_MUSIC), + make_shared(CLIENT_PLAYER_STATE, "PLAYER_STATE", "0", TYPE_UNSIGNED_NUMBER, FLAG_NEW | FLAG_CLIENT_VIEW | FLAG_SAVE_MUSIC), + make_shared(CLIENT_PLAYER_VOLUME, "PLAYER_VOLUME", "1", TYPE_FLOAT, FLAG_NEW | FLAG_SAVE_MUSIC | FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE), + make_shared(CLIENT_PLAYLIST_ID, "CLIENT_PLAYLIST_ID", "0", TYPE_UNSIGNED_NUMBER, FLAG_NEW | FLAG_CLIENT_VARIABLE | FLAG_SAVE_MUSIC), + make_shared(CLIENT_DISABLED, "CLIENT_DISABLED", "0", TYPE_BOOL, FLAG_NEW | FLAG_CLIENT_VARIABLE), + make_shared(CLIENT_UPTIME_MODE, "CLIENT_UPTIME_MODE", "0", TYPE_UNSIGNED_NUMBER, FLAG_NEW | FLAG_CLIENT_VARIABLE | FLAG_USER_EDITABLE | FLAG_SAVE_MUSIC), + make_shared(CLIENT_FLAG_NOTIFY_SONG_CHANGE, "CLIENT_FLAG_NOTIFY_SONG_CHANGE", "1", TYPE_BOOL, FLAG_NEW | FLAG_CLIENT_VARIABLE | FLAG_USER_EDITABLE | FLAG_SAVE_MUSIC) + }; - #define str(s) #s - #define V(key, flags) key, str(key), "0", TYPE_UNSIGNED_NUMBER, flags - #define F(key, flags) key, str(key), "0", TYPE_FLOAT, flags + #define str(s) #s + #define V(key, flags) key, str(key), "0", TYPE_UNSIGNED_NUMBER, flags + #define F(key, flags) key, str(key), "0", TYPE_FLOAT, flags - array, ConnectionProperties::CONNECTION_ENDMARKER> connection_info = { - make_shared(CONNECTION_UNDEFINED, "CONNECTION_UNDEFINED", "undefined", TYPE_UNKNOWN, 0), - make_shared(CONNECTION_PING, "CONNECTION_PING", "0", TYPE_UNSIGNED_NUMBER, 0), //average latency for a round trip through and back this connection - make_shared(CONNECTION_PING_DEVIATION, "CONNECTION_PING_DEVIATION", "0", TYPE_UNSIGNED_NUMBER, 0), //standard deviation of the above average latency - make_shared(CONNECTION_CONNECTED_TIME, "CONNECTION_CONNECTED_TIME", "0", TYPE_UNSIGNED_NUMBER, 0), //how long the connection exists already - make_shared(CONNECTION_IDLE_TIME, "CONNECTION_IDLE_TIME", "0", TYPE_UNSIGNED_NUMBER, 0), //how long since the last action of this manager - make_shared(CONNECTION_CLIENT_IP, "CONNECTION_CLIENT_IP", "", TYPE_STRING, FLAG_SAVE), //NEED DB SAVE! //IP of this manager (as seen from the server side) - make_shared(CONNECTION_CLIENT_PORT, "CONNECTION_CLIENT_PORT", "0", TYPE_UNSIGNED_NUMBER, 0), //Port of this manager (as seen from the server side) - make_shared(CONNECTION_SERVER_IP, "CONNECTION_SERVER_IP", "", TYPE_STRING, 0), //IP of the server (seen from the manager side) - only available on yourself, not for remote clients, not available server side - make_shared(CONNECTION_SERVER_PORT, "CONNECTION_SERVER_PORT", "0", TYPE_UNSIGNED_NUMBER, 0), //Port of the server (seen from the manager side) - only available on yourself, not for remote clients, not available server side - make_shared(V(CONNECTION_PACKETS_SENT_SPEECH, 0)), //how many Speech packets were sent through this connection - make_shared(V(CONNECTION_PACKETS_SENT_KEEPALIVE, 0)), - make_shared(V(CONNECTION_PACKETS_SENT_CONTROL,0)), - make_shared(V(CONNECTION_PACKETS_SENT_TOTAL, FLAG_CLIENT_INFO)), //how many packets were sent totally (this is PACKETS_SENT_SPEECH + PACKETS_SENT_KEEPALIVE + PACKETS_SENT_CONTROL) - make_shared(V(CONNECTION_BYTES_SENT_SPEECH, 0)), - make_shared(V(CONNECTION_BYTES_SENT_KEEPALIVE, 0)), - make_shared(V(CONNECTION_BYTES_SENT_CONTROL, 0)), - make_shared(V(CONNECTION_BYTES_SENT_TOTAL, FLAG_CLIENT_INFO)), - make_shared(V(CONNECTION_PACKETS_RECEIVED_SPEECH, 0)), - make_shared(V(CONNECTION_PACKETS_RECEIVED_KEEPALIVE, 0)), - make_shared(V(CONNECTION_PACKETS_RECEIVED_CONTROL, 0)), - make_shared(V(CONNECTION_PACKETS_RECEIVED_TOTAL, FLAG_CLIENT_INFO)), - make_shared(V(CONNECTION_BYTES_RECEIVED_SPEECH, 0)), - make_shared(V(CONNECTION_BYTES_RECEIVED_KEEPALIVE, 0)), - make_shared(V(CONNECTION_BYTES_RECEIVED_CONTROL, 0)), - make_shared(V(CONNECTION_BYTES_RECEIVED_TOTAL, FLAG_CLIENT_INFO)), - make_shared(F(CONNECTION_PACKETLOSS_SPEECH, 0)), - make_shared(F(CONNECTION_PACKETLOSS_KEEPALIVE, 0)), - make_shared(F(CONNECTION_PACKETLOSS_CONTROL, 0)), - make_shared(F(CONNECTION_PACKETLOSS_TOTAL, FLAG_CLIENT_INFO)), //the probability with which a packet round trip failed because a packet was lost - make_shared(F(CONNECTION_SERVER2CLIENT_PACKETLOSS_SPEECH, 0)), //the probability with which a speech packet failed from the server to the manager - make_shared(F(CONNECTION_SERVER2CLIENT_PACKETLOSS_KEEPALIVE, 0)), - make_shared(F(CONNECTION_SERVER2CLIENT_PACKETLOSS_CONTROL, 0)), - make_shared(F(CONNECTION_SERVER2CLIENT_PACKETLOSS_TOTAL, FLAG_CLIENT_INFO)), - make_shared(F(CONNECTION_CLIENT2SERVER_PACKETLOSS_SPEECH, 0)), - make_shared(F(CONNECTION_CLIENT2SERVER_PACKETLOSS_KEEPALIVE, 0)), - make_shared(F(CONNECTION_CLIENT2SERVER_PACKETLOSS_CONTROL, 0)), - make_shared(F(CONNECTION_CLIENT2SERVER_PACKETLOSS_TOTAL, FLAG_CLIENT_INFO)), - make_shared(V(CONNECTION_BANDWIDTH_SENT_LAST_SECOND_SPEECH, 0)), //howmany bytes of speech packets we sent during the last second - make_shared(V(CONNECTION_BANDWIDTH_SENT_LAST_SECOND_KEEPALIVE, 0)), - make_shared(V(CONNECTION_BANDWIDTH_SENT_LAST_SECOND_CONTROL, 0)), - make_shared(V(CONNECTION_BANDWIDTH_SENT_LAST_SECOND_TOTAL,FLAG_CLIENT_INFO)), - make_shared(V(CONNECTION_BANDWIDTH_SENT_LAST_MINUTE_SPEECH,0)), //howmany bytes/s of speech packets we sent in average during the last minute - make_shared(V(CONNECTION_BANDWIDTH_SENT_LAST_MINUTE_KEEPALIVE,0)), - make_shared(V(CONNECTION_BANDWIDTH_SENT_LAST_MINUTE_CONTROL,0)), - make_shared(V(CONNECTION_BANDWIDTH_SENT_LAST_MINUTE_TOTAL,FLAG_CLIENT_INFO)), - make_shared(V(CONNECTION_BANDWIDTH_RECEIVED_LAST_SECOND_SPEECH, 0)), - make_shared(V(CONNECTION_BANDWIDTH_RECEIVED_LAST_SECOND_KEEPALIVE,0)), - make_shared(V(CONNECTION_BANDWIDTH_RECEIVED_LAST_SECOND_CONTROL,0)), - make_shared(V(CONNECTION_BANDWIDTH_RECEIVED_LAST_SECOND_TOTAL,FLAG_CLIENT_INFO)), - make_shared(V(CONNECTION_BANDWIDTH_RECEIVED_LAST_MINUTE_SPEECH,0)), - make_shared(V(CONNECTION_BANDWIDTH_RECEIVED_LAST_MINUTE_KEEPALIVE,0)), - make_shared(V(CONNECTION_BANDWIDTH_RECEIVED_LAST_MINUTE_CONTROL,0)), - make_shared(V(CONNECTION_BANDWIDTH_RECEIVED_LAST_MINUTE_TOTAL,FLAG_CLIENT_INFO)), + array, ConnectionProperties::CONNECTION_ENDMARKER> connection_info = { + make_shared(CONNECTION_UNDEFINED, "CONNECTION_UNDEFINED", "undefined", TYPE_UNKNOWN, 0), + make_shared(CONNECTION_PING, "CONNECTION_PING", "0", TYPE_UNSIGNED_NUMBER, 0), //average latency for a round trip through and back this connection + make_shared(CONNECTION_PING_DEVIATION, "CONNECTION_PING_DEVIATION", "0", TYPE_UNSIGNED_NUMBER, 0), //standard deviation of the above average latency + make_shared(CONNECTION_CONNECTED_TIME, "CONNECTION_CONNECTED_TIME", "0", TYPE_UNSIGNED_NUMBER, 0), //how long the connection exists already + make_shared(CONNECTION_IDLE_TIME, "CONNECTION_IDLE_TIME", "0", TYPE_UNSIGNED_NUMBER, 0), //how long since the last action of this manager + make_shared(CONNECTION_CLIENT_IP, "CONNECTION_CLIENT_IP", "", TYPE_STRING, FLAG_SAVE), //NEED DB SAVE! //IP of this manager (as seen from the server side) + make_shared(CONNECTION_CLIENT_PORT, "CONNECTION_CLIENT_PORT", "0", TYPE_UNSIGNED_NUMBER, 0), //Port of this manager (as seen from the server side) + make_shared(CONNECTION_SERVER_IP, "CONNECTION_SERVER_IP", "", TYPE_STRING, 0), //IP of the server (seen from the manager side) - only available on yourself, not for remote clients, not available server side + make_shared(CONNECTION_SERVER_PORT, "CONNECTION_SERVER_PORT", "0", TYPE_UNSIGNED_NUMBER, 0), //Port of the server (seen from the manager side) - only available on yourself, not for remote clients, not available server side + make_shared(V(CONNECTION_PACKETS_SENT_SPEECH, 0)), //how many Speech packets were sent through this connection + make_shared(V(CONNECTION_PACKETS_SENT_KEEPALIVE, 0)), + make_shared(V(CONNECTION_PACKETS_SENT_CONTROL,0)), + make_shared(V(CONNECTION_PACKETS_SENT_TOTAL, FLAG_CLIENT_INFO)), //how many packets were sent totally (this is PACKETS_SENT_SPEECH + PACKETS_SENT_KEEPALIVE + PACKETS_SENT_CONTROL) + make_shared(V(CONNECTION_BYTES_SENT_SPEECH, 0)), + make_shared(V(CONNECTION_BYTES_SENT_KEEPALIVE, 0)), + make_shared(V(CONNECTION_BYTES_SENT_CONTROL, 0)), + make_shared(V(CONNECTION_BYTES_SENT_TOTAL, FLAG_CLIENT_INFO)), + make_shared(V(CONNECTION_PACKETS_RECEIVED_SPEECH, 0)), + make_shared(V(CONNECTION_PACKETS_RECEIVED_KEEPALIVE, 0)), + make_shared(V(CONNECTION_PACKETS_RECEIVED_CONTROL, 0)), + make_shared(V(CONNECTION_PACKETS_RECEIVED_TOTAL, FLAG_CLIENT_INFO)), + make_shared(V(CONNECTION_BYTES_RECEIVED_SPEECH, 0)), + make_shared(V(CONNECTION_BYTES_RECEIVED_KEEPALIVE, 0)), + make_shared(V(CONNECTION_BYTES_RECEIVED_CONTROL, 0)), + make_shared(V(CONNECTION_BYTES_RECEIVED_TOTAL, FLAG_CLIENT_INFO)), + make_shared(F(CONNECTION_PACKETLOSS_SPEECH, 0)), + make_shared(F(CONNECTION_PACKETLOSS_KEEPALIVE, 0)), + make_shared(F(CONNECTION_PACKETLOSS_CONTROL, 0)), + make_shared(F(CONNECTION_PACKETLOSS_TOTAL, FLAG_CLIENT_INFO)), //the probability with which a packet round trip failed because a packet was lost + make_shared(F(CONNECTION_SERVER2CLIENT_PACKETLOSS_SPEECH, 0)), //the probability with which a speech packet failed from the server to the manager + make_shared(F(CONNECTION_SERVER2CLIENT_PACKETLOSS_KEEPALIVE, 0)), + make_shared(F(CONNECTION_SERVER2CLIENT_PACKETLOSS_CONTROL, 0)), + make_shared(F(CONNECTION_SERVER2CLIENT_PACKETLOSS_TOTAL, FLAG_CLIENT_INFO)), + make_shared(F(CONNECTION_CLIENT2SERVER_PACKETLOSS_SPEECH, 0)), + make_shared(F(CONNECTION_CLIENT2SERVER_PACKETLOSS_KEEPALIVE, 0)), + make_shared(F(CONNECTION_CLIENT2SERVER_PACKETLOSS_CONTROL, 0)), + make_shared(F(CONNECTION_CLIENT2SERVER_PACKETLOSS_TOTAL, FLAG_CLIENT_INFO)), + make_shared(V(CONNECTION_BANDWIDTH_SENT_LAST_SECOND_SPEECH, 0)), //howmany bytes of speech packets we sent during the last second + make_shared(V(CONNECTION_BANDWIDTH_SENT_LAST_SECOND_KEEPALIVE, 0)), + make_shared(V(CONNECTION_BANDWIDTH_SENT_LAST_SECOND_CONTROL, 0)), + make_shared(V(CONNECTION_BANDWIDTH_SENT_LAST_SECOND_TOTAL,FLAG_CLIENT_INFO)), + make_shared(V(CONNECTION_BANDWIDTH_SENT_LAST_MINUTE_SPEECH,0)), //howmany bytes/s of speech packets we sent in average during the last minute + make_shared(V(CONNECTION_BANDWIDTH_SENT_LAST_MINUTE_KEEPALIVE,0)), + make_shared(V(CONNECTION_BANDWIDTH_SENT_LAST_MINUTE_CONTROL,0)), + make_shared(V(CONNECTION_BANDWIDTH_SENT_LAST_MINUTE_TOTAL,FLAG_CLIENT_INFO)), + make_shared(V(CONNECTION_BANDWIDTH_RECEIVED_LAST_SECOND_SPEECH, 0)), + make_shared(V(CONNECTION_BANDWIDTH_RECEIVED_LAST_SECOND_KEEPALIVE,0)), + make_shared(V(CONNECTION_BANDWIDTH_RECEIVED_LAST_SECOND_CONTROL,0)), + make_shared(V(CONNECTION_BANDWIDTH_RECEIVED_LAST_SECOND_TOTAL,FLAG_CLIENT_INFO)), + make_shared(V(CONNECTION_BANDWIDTH_RECEIVED_LAST_MINUTE_SPEECH,0)), + make_shared(V(CONNECTION_BANDWIDTH_RECEIVED_LAST_MINUTE_KEEPALIVE,0)), + make_shared(V(CONNECTION_BANDWIDTH_RECEIVED_LAST_MINUTE_CONTROL,0)), + make_shared(V(CONNECTION_BANDWIDTH_RECEIVED_LAST_MINUTE_TOTAL,FLAG_CLIENT_INFO)), - //Rare properties - make_shared(V(CONNECTION_FILETRANSFER_BANDWIDTH_SENT, FLAG_CLIENT_INFO)), //how many bytes per second are currently being sent by file transfers - make_shared(V(CONNECTION_FILETRANSFER_BANDWIDTH_RECEIVED, FLAG_CLIENT_INFO)), //how many bytes per second are currently being received by file transfers - make_shared(V(CONNECTION_FILETRANSFER_BYTES_RECEIVED_TOTAL, FLAG_CLIENT_INFO)), //how many bytes we received in total through file transfers - make_shared(V(CONNECTION_FILETRANSFER_BYTES_SENT_TOTAL, FLAG_CLIENT_INFO)) //how many bytes we sent in total through file transfers - }; + //Rare properties + make_shared(V(CONNECTION_FILETRANSFER_BANDWIDTH_SENT, FLAG_CLIENT_INFO)), //how many bytes per second are currently being sent by file transfers + make_shared(V(CONNECTION_FILETRANSFER_BANDWIDTH_RECEIVED, FLAG_CLIENT_INFO)), //how many bytes per second are currently being received by file transfers + make_shared(V(CONNECTION_FILETRANSFER_BYTES_RECEIVED_TOTAL, FLAG_CLIENT_INFO)), //how many bytes we received in total through file transfers + make_shared(V(CONNECTION_FILETRANSFER_BYTES_SENT_TOTAL, FLAG_CLIENT_INFO)) //how many bytes we sent in total through file transfers + }; - array, InstanceProperties::SERVERINSTANCE_ENDMARKER> instance_info = { - make_shared(SERVERINSTANCE_UNDEFINED, "SERVERINSTANCE_UNDEFINED", "undefined", TYPE_UNKNOWN, 0), - make_shared(SERVERINSTANCE_DATABASE_VERSION, "SERVERINSTANCE_DATABASE_VERSION", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE), - make_shared(SERVERINSTANCE_PERMISSIONS_VERSION, "SERVERINSTANCE_PERMISSIONS_VERSION", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE), - make_shared(SERVERINSTANCE_FILETRANSFER_HOST, "SERVERINSTANCE_FILETRANSFER_HOST", "0.0.0.0,[::]", TYPE_STRING, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), - make_shared(SERVERINSTANCE_FILETRANSFER_PORT, "SERVERINSTANCE_FILETRANSFER_PORT", "30303", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), - make_shared(SERVERINSTANCE_FILETRANSFER_MAX_CONNECTIONS, "SERVERINSTANCE_FILETRANSFER_MAX_CONNECTIONS", "100", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), - make_shared(SERVERINSTANCE_FILETRANSFER_MAX_CONNECTIONS_PER_IP, "SERVERINSTANCE_FILETRANSFER_MAX_CONNECTIONS_PER_IP", "20", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), - make_shared(SERVERINSTANCE_QUERY_HOST, "SERVERINSTANCE_QUERY_HOST", "0.0.0.0,[::]", TYPE_STRING, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), - make_shared(SERVERINSTANCE_QUERY_PORT, "SERVERINSTANCE_QUERY_PORT", "10101", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), - make_shared(SERVERINSTANCE_QUERY_MAX_CONNECTIONS, "SERVERINSTANCE_QUERY_MAX_CONNECTIONS", "100", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), - make_shared(SERVERINSTANCE_QUERY_MAX_CONNECTIONS_PER_IP, "SERVERINSTANCE_QUERY_MAX_CONNECTIONS_PER_IP", "3", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), - make_shared(SERVERINSTANCE_MONTHLY_TIMESTAMP, "SERVERINSTANCE_MONTHLY_TIMESTAMP", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), - make_shared(SERVERINSTANCE_MAX_DOWNLOAD_TOTAL_BANDWIDTH, "SERVERINSTANCE_MAX_DOWNLOAD_TOTAL_BANDWIDTH", "-1", TYPE_SIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), - make_shared(SERVERINSTANCE_MAX_UPLOAD_TOTAL_BANDWIDTH, "SERVERINSTANCE_MAX_UPLOAD_TOTAL_BANDWIDTH", "-1", TYPE_SIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), - make_shared(SERVERINSTANCE_SERVERQUERY_FLOOD_COMMANDS, "SERVERINSTANCE_SERVERQUERY_FLOOD_COMMANDS", "3", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), //how many commands we can issue while in the SERVERINSTANCE_SERVERQUERY_FLOOD_TIME window - make_shared(SERVERINSTANCE_SERVERQUERY_FLOOD_TIME, "SERVERINSTANCE_SERVERQUERY_FLOOD_TIME", "1", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), //time window in seconds for max command execution check - make_shared(SERVERINSTANCE_SERVERQUERY_BAN_TIME, "SERVERINSTANCE_SERVERQUERY_BAN_TIME", "600", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), //how many seconds someone get banned if he floods - make_shared(SERVERINSTANCE_TEMPLATE_SERVERADMIN_GROUP, "SERVERINSTANCE_TEMPLATE_SERVERADMIN_GROUP", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), - make_shared(SERVERINSTANCE_TEMPLATE_SERVERDEFAULT_GROUP, "SERVERINSTANCE_TEMPLATE_SERVERDEFAULT_GROUP", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), - make_shared(SERVERINSTANCE_TEMPLATE_CHANNELADMIN_GROUP, "SERVERINSTANCE_TEMPLATE_CHANNELADMIN_GROUP", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), - make_shared(SERVERINSTANCE_TEMPLATE_CHANNELDEFAULT_GROUP, "SERVERINSTANCE_TEMPLATE_CHANNELDEFAULT_GROUP", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), - make_shared(SERVERINSTANCE_TEMPLATE_MUSICDEFAULT_GROUP, "SERVERINSTANCE_TEMPLATE_MUSICDEFAULT_GROUP", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), - make_shared(SERVERINSTANCE_GUEST_SERVERQUERY_GROUP, "SERVERINSTANCE_GUEST_SERVERQUERY_GROUP", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), - make_shared(SERVERINSTANCE_ADMIN_SERVERQUERY_GROUP, "SERVERINSTANCE_ADMIN_SERVERQUERY_GROUP", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), - make_shared(SERVERINSTANCE_PENDING_CONNECTIONS_PER_IP, "SERVERINSTANCE_PENDING_CONNECTIONS_PER_IP", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), - make_shared(SERVERINSTANCE_SPOKEN_TIME_TOTAL, "SERVERINSTANCE_SPOKEN_TIME_TOTAL", "0", TYPE_UNSIGNED_NUMBER, FLAG_INTERNAL | FLAG_SAVE | FLAG_NEW), - make_shared(SERVERINSTANCE_SPOKEN_TIME_DELETED, "SERVERINSTANCE_SPOKEN_TIME_DELETED", "0", TYPE_UNSIGNED_NUMBER, FLAG_INTERNAL | FLAG_SAVE | FLAG_NEW), - make_shared(SERVERINSTANCE_SPOKEN_TIME_ALIVE, "SERVERINSTANCE_SPOKEN_TIME_ALIVE", "0", TYPE_UNSIGNED_NUMBER, FLAG_INTERNAL | FLAG_SAVE | FLAG_NEW), - make_shared(SERVERINSTANCE_SPOKEN_TIME_VARIANZ, "SERVERINSTANCE_SPOKEN_TIME_VARIANZ", "0", TYPE_UNSIGNED_NUMBER, FLAG_INTERNAL | FLAG_SAVE | FLAG_NEW), - make_shared(SERVERINSTANCE_VIRTUAL_SERVER_ID_INDEX, "SERVERINSTANCE_VIRTUAL_SERVER_ID_INDEX", "1", TYPE_UNSIGNED_NUMBER, FLAG_SAVE | FLAG_INSTANCE_VARIABLE | FLAG_NEW), - make_shared(SERVERINSTANCE_UNIQUE_ID, "SERVERINSTANCE_UNIQUE_ID", "", TYPE_STRING, FLAG_INTERNAL | FLAG_SAVE | FLAG_NEW), - }; + array, InstanceProperties::SERVERINSTANCE_ENDMARKER> instance_info = { + make_shared(SERVERINSTANCE_UNDEFINED, "SERVERINSTANCE_UNDEFINED", "undefined", TYPE_UNKNOWN, 0), + make_shared(SERVERINSTANCE_DATABASE_VERSION, "SERVERINSTANCE_DATABASE_VERSION", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE), + make_shared(SERVERINSTANCE_PERMISSIONS_VERSION, "SERVERINSTANCE_PERMISSIONS_VERSION", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE), + make_shared(SERVERINSTANCE_FILETRANSFER_HOST, "SERVERINSTANCE_FILETRANSFER_HOST", "0.0.0.0,[::]", TYPE_STRING, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), + make_shared(SERVERINSTANCE_FILETRANSFER_PORT, "SERVERINSTANCE_FILETRANSFER_PORT", "30303", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), + make_shared(SERVERINSTANCE_FILETRANSFER_MAX_CONNECTIONS, "SERVERINSTANCE_FILETRANSFER_MAX_CONNECTIONS", "100", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), + make_shared(SERVERINSTANCE_FILETRANSFER_MAX_CONNECTIONS_PER_IP, "SERVERINSTANCE_FILETRANSFER_MAX_CONNECTIONS_PER_IP", "20", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), + make_shared(SERVERINSTANCE_QUERY_HOST, "SERVERINSTANCE_QUERY_HOST", "0.0.0.0,[::]", TYPE_STRING, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), + make_shared(SERVERINSTANCE_QUERY_PORT, "SERVERINSTANCE_QUERY_PORT", "10101", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), + make_shared(SERVERINSTANCE_QUERY_MAX_CONNECTIONS, "SERVERINSTANCE_QUERY_MAX_CONNECTIONS", "100", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), + make_shared(SERVERINSTANCE_QUERY_MAX_CONNECTIONS_PER_IP, "SERVERINSTANCE_QUERY_MAX_CONNECTIONS_PER_IP", "3", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), + make_shared(SERVERINSTANCE_MONTHLY_TIMESTAMP, "SERVERINSTANCE_MONTHLY_TIMESTAMP", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), + make_shared(SERVERINSTANCE_MAX_DOWNLOAD_TOTAL_BANDWIDTH, "SERVERINSTANCE_MAX_DOWNLOAD_TOTAL_BANDWIDTH", "-1", TYPE_SIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), + make_shared(SERVERINSTANCE_MAX_UPLOAD_TOTAL_BANDWIDTH, "SERVERINSTANCE_MAX_UPLOAD_TOTAL_BANDWIDTH", "-1", TYPE_SIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), + make_shared(SERVERINSTANCE_SERVERQUERY_FLOOD_COMMANDS, "SERVERINSTANCE_SERVERQUERY_FLOOD_COMMANDS", "3", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), //how many commands we can issue while in the SERVERINSTANCE_SERVERQUERY_FLOOD_TIME window + make_shared(SERVERINSTANCE_SERVERQUERY_FLOOD_TIME, "SERVERINSTANCE_SERVERQUERY_FLOOD_TIME", "1", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), //time window in seconds for max command execution check + make_shared(SERVERINSTANCE_SERVERQUERY_BAN_TIME, "SERVERINSTANCE_SERVERQUERY_BAN_TIME", "600", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), //how many seconds someone get banned if he floods + make_shared(SERVERINSTANCE_TEMPLATE_SERVERADMIN_GROUP, "SERVERINSTANCE_TEMPLATE_SERVERADMIN_GROUP", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), + make_shared(SERVERINSTANCE_TEMPLATE_SERVERDEFAULT_GROUP, "SERVERINSTANCE_TEMPLATE_SERVERDEFAULT_GROUP", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), + make_shared(SERVERINSTANCE_TEMPLATE_CHANNELADMIN_GROUP, "SERVERINSTANCE_TEMPLATE_CHANNELADMIN_GROUP", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), + make_shared(SERVERINSTANCE_TEMPLATE_CHANNELDEFAULT_GROUP, "SERVERINSTANCE_TEMPLATE_CHANNELDEFAULT_GROUP", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), + make_shared(SERVERINSTANCE_TEMPLATE_MUSICDEFAULT_GROUP, "SERVERINSTANCE_TEMPLATE_MUSICDEFAULT_GROUP", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), + make_shared(SERVERINSTANCE_GUEST_SERVERQUERY_GROUP, "SERVERINSTANCE_GUEST_SERVERQUERY_GROUP", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), + make_shared(SERVERINSTANCE_ADMIN_SERVERQUERY_GROUP, "SERVERINSTANCE_ADMIN_SERVERQUERY_GROUP", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), + make_shared(SERVERINSTANCE_PENDING_CONNECTIONS_PER_IP, "SERVERINSTANCE_PENDING_CONNECTIONS_PER_IP", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE), + make_shared(SERVERINSTANCE_SPOKEN_TIME_TOTAL, "SERVERINSTANCE_SPOKEN_TIME_TOTAL", "0", TYPE_UNSIGNED_NUMBER, FLAG_INTERNAL | FLAG_SAVE | FLAG_NEW), + make_shared(SERVERINSTANCE_SPOKEN_TIME_DELETED, "SERVERINSTANCE_SPOKEN_TIME_DELETED", "0", TYPE_UNSIGNED_NUMBER, FLAG_INTERNAL | FLAG_SAVE | FLAG_NEW), + make_shared(SERVERINSTANCE_SPOKEN_TIME_ALIVE, "SERVERINSTANCE_SPOKEN_TIME_ALIVE", "0", TYPE_UNSIGNED_NUMBER, FLAG_INTERNAL | FLAG_SAVE | FLAG_NEW), + make_shared(SERVERINSTANCE_SPOKEN_TIME_VARIANZ, "SERVERINSTANCE_SPOKEN_TIME_VARIANZ", "0", TYPE_UNSIGNED_NUMBER, FLAG_INTERNAL | FLAG_SAVE | FLAG_NEW), + make_shared(SERVERINSTANCE_VIRTUAL_SERVER_ID_INDEX, "SERVERINSTANCE_VIRTUAL_SERVER_ID_INDEX", "1", TYPE_UNSIGNED_NUMBER, FLAG_SAVE | FLAG_INSTANCE_VARIABLE | FLAG_NEW), + make_shared(SERVERINSTANCE_UNIQUE_ID, "SERVERINSTANCE_UNIQUE_ID", "", TYPE_STRING, FLAG_INTERNAL | FLAG_SAVE | FLAG_NEW), + }; - array, PlaylistProperties::PLAYLIST_ENDMARKER> playlist_info = { - make_shared(PLAYLIST_UNDEFINED, "PLAYLIST_UNDEFINED", "undefined", TYPE_UNKNOWN, 0), - make_shared(PLAYLIST_ID, "PLAYLIST_ID", "0", TYPE_UNSIGNED_NUMBER, FLAG_PLAYLIST_VARIABLE), - make_shared(PLAYLIST_TYPE, "PLAYLIST_TYPE", "0", TYPE_UNSIGNED_NUMBER, FLAG_PLAYLIST_VARIABLE | FLAG_SAVE), - make_shared(PLAYLIST_TITLE, "PLAYLIST_TITLE", "Yet another playlist", TYPE_STRING, FLAG_PLAYLIST_VARIABLE | FLAG_USER_EDITABLE | FLAG_SAVE), - make_shared(PLAYLIST_DESCRIPTION, "PLAYLIST_DESCRIPTION", "", TYPE_STRING, FLAG_PLAYLIST_VARIABLE | FLAG_USER_EDITABLE | FLAG_SAVE), - make_shared(PLAYLIST_OWNER_DBID, "PLAYLIST_OWNER_DBID", "0", TYPE_UNSIGNED_NUMBER, FLAG_PLAYLIST_VARIABLE | FLAG_SAVE), - make_shared(PLAYLIST_OWNER_NAME, "PLAYLIST_OWNER_NAME", "0", TYPE_STRING, FLAG_PLAYLIST_VARIABLE | FLAG_SAVE), - make_shared(PLAYLIST_FLAG_DELETE_PLAYED, "PLAYLIST_FLAG_DELETE_PLAYED", "1", TYPE_BOOL, FLAG_PLAYLIST_VARIABLE | FLAG_USER_EDITABLE | FLAG_SAVE), - make_shared(PLAYLIST_REPLAY_MODE, "PLAYLIST_REPLAY_MODE", "0", TYPE_UNSIGNED_NUMBER, FLAG_PLAYLIST_VARIABLE | FLAG_USER_EDITABLE | FLAG_SAVE), - make_shared(PLAYLIST_CURRENT_SONG_ID, "PLAYLIST_CURRENT_SONG_ID", "0", TYPE_UNSIGNED_NUMBER, FLAG_PLAYLIST_VARIABLE | FLAG_SAVE), - make_shared(PLAYLIST_FLAG_FINISHED, "PLAYLIST_FLAG_FINISHED", "0", TYPE_BOOL, FLAG_PLAYLIST_VARIABLE | FLAG_USER_EDITABLE | FLAG_SAVE), - make_shared(PLAYLIST_MAX_SONGS, "PLAYLIST_MAX_SONGS", "-1", TYPE_SIGNED_NUMBER, FLAG_PLAYLIST_VARIABLE | FLAG_USER_EDITABLE | FLAG_SAVE), - }; + array, PlaylistProperties::PLAYLIST_ENDMARKER> playlist_info = { + make_shared(PLAYLIST_UNDEFINED, "PLAYLIST_UNDEFINED", "undefined", TYPE_UNKNOWN, 0), + make_shared(PLAYLIST_ID, "PLAYLIST_ID", "0", TYPE_UNSIGNED_NUMBER, FLAG_PLAYLIST_VARIABLE), + make_shared(PLAYLIST_TYPE, "PLAYLIST_TYPE", "0", TYPE_UNSIGNED_NUMBER, FLAG_PLAYLIST_VARIABLE | FLAG_SAVE), + make_shared(PLAYLIST_TITLE, "PLAYLIST_TITLE", "Yet another playlist", TYPE_STRING, FLAG_PLAYLIST_VARIABLE | FLAG_USER_EDITABLE | FLAG_SAVE), + make_shared(PLAYLIST_DESCRIPTION, "PLAYLIST_DESCRIPTION", "", TYPE_STRING, FLAG_PLAYLIST_VARIABLE | FLAG_USER_EDITABLE | FLAG_SAVE), + make_shared(PLAYLIST_OWNER_DBID, "PLAYLIST_OWNER_DBID", "0", TYPE_UNSIGNED_NUMBER, FLAG_PLAYLIST_VARIABLE | FLAG_SAVE), + make_shared(PLAYLIST_OWNER_NAME, "PLAYLIST_OWNER_NAME", "0", TYPE_STRING, FLAG_PLAYLIST_VARIABLE | FLAG_SAVE), + make_shared(PLAYLIST_FLAG_DELETE_PLAYED, "PLAYLIST_FLAG_DELETE_PLAYED", "1", TYPE_BOOL, FLAG_PLAYLIST_VARIABLE | FLAG_USER_EDITABLE | FLAG_SAVE), + make_shared(PLAYLIST_REPLAY_MODE, "PLAYLIST_REPLAY_MODE", "0", TYPE_UNSIGNED_NUMBER, FLAG_PLAYLIST_VARIABLE | FLAG_USER_EDITABLE | FLAG_SAVE), + make_shared(PLAYLIST_CURRENT_SONG_ID, "PLAYLIST_CURRENT_SONG_ID", "0", TYPE_UNSIGNED_NUMBER, FLAG_PLAYLIST_VARIABLE | FLAG_SAVE), + make_shared(PLAYLIST_FLAG_FINISHED, "PLAYLIST_FLAG_FINISHED", "0", TYPE_BOOL, FLAG_PLAYLIST_VARIABLE | FLAG_USER_EDITABLE | FLAG_SAVE), + make_shared(PLAYLIST_MAX_SONGS, "PLAYLIST_MAX_SONGS", "-1", TYPE_SIGNED_NUMBER, FLAG_PLAYLIST_VARIABLE | FLAG_USER_EDITABLE | FLAG_SAVE), + }; - shared_ptr PropertyDescription::unknown = make_shared(UNKNOWN_UNDEFINED, "undefined", "", ValueType::TYPE_UNKNOWN, 0); - namespace impl { - #define M(type, _info) \ - template <> \ - const std::shared_ptr& info(type type) { \ - for(const auto& element : (_info)) \ - if(element->property_index == (type)) \ - return element; \ - return (_info)[0]; \ - } \ - \ - template <> \ - const std::shared_ptr& info(const std::string& _type) { \ - for(const auto& element : (_info)) \ - if(element->name == _type) \ - return element; \ - return (_info)[0]; \ - } \ + shared_ptr PropertyDescription::unknown = make_shared(UNKNOWN_UNDEFINED, "undefined", "", ValueType::TYPE_UNKNOWN, 0); + namespace impl { + #define M(type, _info) \ + template <> \ + const std::shared_ptr& info(type type) { \ + for(const auto& element : (_info)) \ + if(element->property_index == (type)) \ + return element; \ + return (_info)[0]; \ + } \ + \ + template <> \ + const std::shared_ptr& info(const std::string& _type) { \ + for(const auto& element : (_info)) \ + if(element->name == _type) \ + return element; \ + return (_info)[0]; \ + } \ \ \ template <> \ std::deque> list() { \ return {_info.begin(), _info.end()}; \ - } + } - M(VirtualServerProperties, virtualserver_info); - M(ChannelProperties, channel_info); - M(GroupProperties, group_info); - M(ClientProperties, client_info); - M(ConnectionProperties, connection_info); - M(InstanceProperties, instance_info); - M(PlaylistProperties, playlist_info); + M(VirtualServerProperties, virtualserver_info); + M(ChannelProperties, channel_info); + M(GroupProperties, group_info); + M(ClientProperties, client_info); + M(ConnectionProperties, connection_info); + M(InstanceProperties, instance_info); + M(PlaylistProperties, playlist_info); #define TP(info) \ { for(const auto& prop : (info)) \ if(prop->name == key) return prop; } - const std::shared_ptr& info_key(const std::string& key) { + const std::shared_ptr& info_key(const std::string& key) { TP(virtualserver_info); TP(channel_info); TP(group_info); TP(client_info); TP(connection_info); TP(instance_info); - TP(playlist_info); - return PropertyDescription::unknown; - } + TP(playlist_info); + return PropertyDescription::unknown; + } const std::shared_ptr& info_key(PropertyType type, const std::string& key) { @@ -546,86 +546,86 @@ namespace ts { else if(type == PropertyType::PROP_TYPE_INSTANCE) TP(instance_info) else if(type == PropertyType::PROP_TYPE_PLAYLIST) - TP(playlist_info); + TP(playlist_info); return PropertyDescription::unknown; - } + } - const std::shared_ptr& info(PropertyType type, int index) { - if(type == PropertyType::PROP_TYPE_SERVER) - return impl::info((VirtualServerProperties) index); - else if(type == PropertyType::PROP_TYPE_CHANNEL) - return impl::info((ChannelProperties) index); - else if(type == PropertyType::PROP_TYPE_CLIENT) - return impl::info((ClientProperties) index); - else if(type == PropertyType::PROP_TYPE_GROUP) - return impl::info((GroupProperties) index); - else if(type == PropertyType::PROP_TYPE_CONNECTION) - return impl::info((ConnectionProperties) index); - else if(type == PropertyType::PROP_TYPE_INSTANCE) - return impl::info((InstanceProperties) index); - else if(type == PropertyType::PROP_TYPE_PLAYLIST) - return impl::info((PlaylistProperties) index); - return PropertyDescription::unknown; - } + const std::shared_ptr& info(PropertyType type, int index) { + if(type == PropertyType::PROP_TYPE_SERVER) + return impl::info((VirtualServerProperties) index); + else if(type == PropertyType::PROP_TYPE_CHANNEL) + return impl::info((ChannelProperties) index); + else if(type == PropertyType::PROP_TYPE_CLIENT) + return impl::info((ClientProperties) index); + else if(type == PropertyType::PROP_TYPE_GROUP) + return impl::info((GroupProperties) index); + else if(type == PropertyType::PROP_TYPE_CONNECTION) + return impl::info((ConnectionProperties) index); + else if(type == PropertyType::PROP_TYPE_INSTANCE) + return impl::info((InstanceProperties) index); + else if(type == PropertyType::PROP_TYPE_PLAYLIST) + return impl::info((PlaylistProperties) index); + return PropertyDescription::unknown; + } - #define M1(info) \ - for(const auto& e : (info)){ \ - auto found = find(used.begin(), used.end(), e->name); \ - if(found != used.end()) { \ - cerr << "[CRITICAL] Double registered property! (" << e->name << ")" << endl; \ - return false; \ - } \ - used.push_back(e->name); \ - } + #define M1(info) \ + for(const auto& e : (info)){ \ + auto found = find(used.begin(), used.end(), e->name); \ + if(found != used.end()) { \ + cerr << "[CRITICAL] Double registered property! (" << e->name << ")" << endl; \ + return false; \ + } \ + used.push_back(e->name); \ + } - bool validateUnique() { - deque used; - M1(virtualserver_info); - M1(channel_info); - M1(group_info); - M1(client_info); - M1(connection_info); - M1(instance_info); - M1(playlist_info); - return true; - } + bool validateUnique() { + deque used; + M1(virtualserver_info); + M1(channel_info); + M1(group_info); + M1(client_info); + M1(connection_info); + M1(instance_info); + M1(playlist_info); + return true; + } - bool validateInput(const std::string& input, ValueType type) { - if(type == ValueType::TYPE_UNKNOWN) return true; - else if(type == ValueType::TYPE_UNSIGNED_NUMBER) { - if(input.empty() || input.find_first_not_of("0123456789") != string::npos) return false; - try { - stoull(input); - return true; - } catch (std::exception& /* ex */) { return false; } - } - else if(type == ValueType::TYPE_SIGNED_NUMBER) { - if(input.empty() || input.find_first_not_of("-0123456789") != string::npos) return false; - auto minus = input.find_first_of('-'); - auto flag_result = minus == string::npos || (minus == 0 && input.find_first_of('-', minus + 1) == string::npos); - if(!flag_result) return false; + bool validateInput(const std::string& input, ValueType type) { + if(type == ValueType::TYPE_UNKNOWN) return true; + else if(type == ValueType::TYPE_UNSIGNED_NUMBER) { + if(input.empty() || input.find_first_not_of("0123456789") != string::npos) return false; + try { + stoull(input); + return true; + } catch (std::exception& /* ex */) { return false; } + } + else if(type == ValueType::TYPE_SIGNED_NUMBER) { + if(input.empty() || input.find_first_not_of("-0123456789") != string::npos) return false; + auto minus = input.find_first_of('-'); + auto flag_result = minus == string::npos || (minus == 0 && input.find_first_of('-', minus + 1) == string::npos); + if(!flag_result) return false; - try { - stoll(input); - return true; - } catch (std::exception& /* ex */) { return false; } - } else if(type == ValueType::TYPE_BOOL) return input.length() == 1 && input.find_first_not_of("01") == string::npos; - else if(type == ValueType::TYPE_STRING) return true; - else if(type == ValueType::TYPE_FLOAT) { - if(input.empty() || input.find_first_not_of("-.0123456789") != string::npos) return false; - auto minus = input.find_first_of('-'); - if(minus != string::npos && (input.find_first_of('-', minus + 1) != string::npos || minus != 0)) return false; - auto point = input.find_first_of('.'); - auto flag_result = point == string::npos || input.find_first_of('.', point + 1) == string::npos; - if(!flag_result) return false; + try { + stoll(input); + return true; + } catch (std::exception& /* ex */) { return false; } + } else if(type == ValueType::TYPE_BOOL) return input.length() == 1 && input.find_first_not_of("01") == string::npos; + else if(type == ValueType::TYPE_STRING) return true; + else if(type == ValueType::TYPE_FLOAT) { + if(input.empty() || input.find_first_not_of("-.0123456789") != string::npos) return false; + auto minus = input.find_first_of('-'); + if(minus != string::npos && (input.find_first_of('-', minus + 1) != string::npos || minus != 0)) return false; + auto point = input.find_first_of('.'); + auto flag_result = point == string::npos || input.find_first_of('.', point + 1) == string::npos; + if(!flag_result) return false; - try { - stof(input); - return true; - } catch (std::exception& /* ex */) { return false; } - } - return false; - } - } - } + try { + stof(input); + return true; + } catch (std::exception& /* ex */) { return false; } + } + return false; + } + } + } } \ No newline at end of file diff --git a/src/Properties.h b/src/Properties.h index 6cf6223..f975d79 100644 --- a/src/Properties.h +++ b/src/Properties.h @@ -21,596 +21,596 @@ namespace ts { namespace property { - enum PropertyType { - PROP_TYPE_SERVER = 0, - PROP_TYPE_CHANNEL = 1, - PROP_TYPE_GROUP = 2, - PROP_TYPE_CLIENT = 3, - PROP_TYPE_INSTANCE = 4, - PROP_TYPE_CONNECTION = 5, - PROP_TYPE_PLAYLIST = 6, - PROP_TYPE_UNKNOWN = 7 - }; - static constexpr const char *PropertyType_Names[7] = { - "SERVER", - "CHANNEL", - "GROUP", - "CLIENT", - "INSTANCE", - "CONNECTION", - "UNKNOWN" - }; - - enum ValueType { - TYPE_UNKNOWN, - TYPE_STRING, - TYPE_BOOL, - TYPE_SIGNED_NUMBER, - TYPE_UNSIGNED_NUMBER, - TYPE_FLOAT - }; - - typedef uint32_t flag_type; - enum flag : flag_type { - FLAG_BEGIN = 0b1, - FLAG_INTERNAL = FLAG_BEGIN << 1UL, //Just for internal usage - FLAG_GLOBAL = FLAG_INTERNAL << 1UL, //Not server bound - FLAG_SNAPSHOT = FLAG_GLOBAL << 1UL, //Saved within snapshots - FLAG_SAVE = FLAG_SNAPSHOT << 1UL, //Saved to database - FLAG_SAVE_MUSIC = FLAG_SAVE << 1UL, //Saved to database - FLAG_NEW = FLAG_SAVE_MUSIC << 1UL, //Its a non TeamSpeak property - FLAG_SERVER_VARIABLE = FLAG_NEW << 1UL, - FLAG_SERVER_VIEW = FLAG_SERVER_VARIABLE << 1UL, - FLAG_CLIENT_VARIABLE = FLAG_SERVER_VIEW << 1UL, - FLAG_CLIENT_VIEW = FLAG_CLIENT_VARIABLE << 1UL, - FLAG_CLIENT_INFO = FLAG_CLIENT_VIEW << 1UL, - FLAG_CHANNEL_VARIABLE = FLAG_CLIENT_INFO << 1UL, - FLAG_CHANNEL_VIEW = FLAG_CHANNEL_VARIABLE << 1UL, - FLAG_GROUP_VIEW = FLAG_CHANNEL_VIEW << 1UL, - FLAG_INSTANCE_VARIABLE = FLAG_GROUP_VIEW << 1UL, - FLAG_USER_EDITABLE = FLAG_INSTANCE_VARIABLE << 1UL, - FLAG_PLAYLIST_VARIABLE = FLAG_USER_EDITABLE << 1UL, - }; - static constexpr const char *flag_names[sizeof(flag) * 8] = - {"UNDEFINED", "FLAG_INTERNAL", "FLAG_GLOBAL", "FLAG_SNAPSHOT", "FLAG_SAVE", "FLAG_SAVE_MUSIC", "FLAG_NEW", - "FLAG_SERVER_VARIABLE", "FLAG_SERVER_VIEW", "FLAG_CLIENT_VARIABLE", "FLAG_CLIENT_VIEW", "FLAG_CLIENT_INFO", - "FLAG_CHANNEL_VARIABLE", "FLAG_CHANNEL_VIEW", "FLAG_GROUP_VIEW", "FLAG_INSTANCE_VARIABLE", "FLAG_USER_EDITABLE","FLAG_PLAYLIST_VARIABLE"}; - - enum UnknownProperties { - UNKNOWN_UNDEFINED, - UNKNOWN_BEGINMARKER, - UNKNOWN_ENDMARKER = UNKNOWN_BEGINMARKER - }; - - enum InstanceProperties { - SERVERINSTANCE_UNDEFINED, - SERVERINSTANCE_BEGINMARKER, - SERVERINSTANCE_DATABASE_VERSION = SERVERINSTANCE_BEGINMARKER, - SERVERINSTANCE_PERMISSIONS_VERSION, - - SERVERINSTANCE_FILETRANSFER_HOST, - SERVERINSTANCE_FILETRANSFER_PORT, - SERVERINSTANCE_FILETRANSFER_MAX_CONNECTIONS, - SERVERINSTANCE_FILETRANSFER_MAX_CONNECTIONS_PER_IP, - - SERVERINSTANCE_QUERY_HOST, - SERVERINSTANCE_QUERY_PORT, - SERVERINSTANCE_QUERY_MAX_CONNECTIONS, - SERVERINSTANCE_QUERY_MAX_CONNECTIONS_PER_IP, - - SERVERINSTANCE_MONTHLY_TIMESTAMP, - SERVERINSTANCE_MAX_DOWNLOAD_TOTAL_BANDWIDTH, - SERVERINSTANCE_MAX_UPLOAD_TOTAL_BANDWIDTH, - SERVERINSTANCE_SERVERQUERY_FLOOD_COMMANDS, //how many commands we can issue while in the SERVERINSTANCE_SERVERQUERY_FLOOD_TIME window - SERVERINSTANCE_SERVERQUERY_FLOOD_TIME, //time window in seconds for max command execution check - SERVERINSTANCE_SERVERQUERY_BAN_TIME, //how many seconds someone get banned if he floods - SERVERINSTANCE_TEMPLATE_SERVERADMIN_GROUP, - SERVERINSTANCE_TEMPLATE_SERVERDEFAULT_GROUP, - SERVERINSTANCE_TEMPLATE_CHANNELADMIN_GROUP, - SERVERINSTANCE_TEMPLATE_CHANNELDEFAULT_GROUP, - SERVERINSTANCE_TEMPLATE_MUSICDEFAULT_GROUP, - SERVERINSTANCE_GUEST_SERVERQUERY_GROUP, - SERVERINSTANCE_ADMIN_SERVERQUERY_GROUP, - SERVERINSTANCE_PENDING_CONNECTIONS_PER_IP, - SERVERINSTANCE_SPOKEN_TIME_TOTAL, - SERVERINSTANCE_SPOKEN_TIME_DELETED, - SERVERINSTANCE_SPOKEN_TIME_ALIVE, - SERVERINSTANCE_SPOKEN_TIME_VARIANZ, - - SERVERINSTANCE_VIRTUAL_SERVER_ID_INDEX, - - SERVERINSTANCE_UNIQUE_ID, - SERVERINSTANCE_ENDMARKER, - }; - - enum VirtualServerProperties { - VIRTUALSERVER_UNDEFINED = 0, - VIRTUALSERVER_BEGINMARKER, - VIRTUALSERVER_UNIQUE_IDENTIFIER = VIRTUALSERVER_BEGINMARKER, //available when connected, can be used to identify this particular server installation - VIRTUALSERVER_NAME, //available and always up-to-date when connected - VIRTUALSERVER_WELCOMEMESSAGE, //available when connected, (=> requestServerVariables) - VIRTUALSERVER_PLATFORM, //available when connected - VIRTUALSERVER_VERSION, //available when connected - VIRTUALSERVER_MAXCLIENTS, //only available on request (=> requestServerVariables), stores the maximum number of clients that may currently join the server - VIRTUALSERVER_PASSWORD, //not available to clients, the server password - VIRTUALSERVER_CLIENTS_ONLINE, //only available on request (=> requestServerVariables), - VIRTUALSERVER_CHANNELS_ONLINE, //only available on request (=> requestServerVariables), - VIRTUALSERVER_CREATED, //available when connected, stores the time when the server was created - VIRTUALSERVER_UPTIME, //only available on request (=> requestServerVariables), the time since the server was started - VIRTUALSERVER_CODEC_ENCRYPTION_MODE, //available and always up-to-date when connected - - //Rare properties - VIRTUALSERVER_KEYPAIR, //internal use - VIRTUALSERVER_HOSTMESSAGE, //available when connected, not updated while connected - VIRTUALSERVER_HOSTMESSAGE_MODE, //available when connected, not updated while connected - VIRTUALSERVER_FILEBASE, //not available to clients, stores the folder used for file transfers - VIRTUALSERVER_DEFAULT_SERVER_GROUP, //the manager permissions server group that a new manager gets assigned - VIRTUALSERVER_DEFAULT_MUSIC_GROUP, //the manager permissions server group that a new manager gets assigned - VIRTUALSERVER_DEFAULT_CHANNEL_GROUP, //the channel permissions group that a new manager gets assigned when joining a channel - VIRTUALSERVER_FLAG_PASSWORD, //only available on request (=> requestServerVariables) - VIRTUALSERVER_DEFAULT_CHANNEL_ADMIN_GROUP, //the channel permissions group that a manager gets assigned when creating a channel - VIRTUALSERVER_MAX_DOWNLOAD_TOTAL_BANDWIDTH, //only available on request (=> requestServerVariables) - VIRTUALSERVER_MAX_UPLOAD_TOTAL_BANDWIDTH, //only available on request (=> requestServerVariables) - VIRTUALSERVER_HOSTBANNER_URL, //available when connected, always up-to-date - VIRTUALSERVER_HOSTBANNER_GFX_URL, //available when connected, always up-to-date - VIRTUALSERVER_HOSTBANNER_GFX_INTERVAL, //available when connected, always up-to-date - VIRTUALSERVER_COMPLAIN_AUTOBAN_COUNT, //only available on request (=> requestServerVariables) - VIRTUALSERVER_COMPLAIN_AUTOBAN_TIME, //only available on request (=> requestServerVariables) - VIRTUALSERVER_COMPLAIN_REMOVE_TIME, //only available on request (=> requestServerVariables) - VIRTUALSERVER_MIN_CLIENTS_IN_CHANNEL_BEFORE_FORCED_SILENCE,//only available on request (=> requestServerVariables) - VIRTUALSERVER_PRIORITY_SPEAKER_DIMM_MODIFICATOR, //available when connected, always up-to-date - VIRTUALSERVER_ID, //available when connected - VIRTUALSERVER_ANTIFLOOD_POINTS_TICK_REDUCE, //only available on request (=> requestServerVariables) - VIRTUALSERVER_ANTIFLOOD_POINTS_NEEDED_COMMAND_BLOCK, //only available on request (=> requestServerVariables) - VIRTUALSERVER_ANTIFLOOD_POINTS_NEEDED_IP_BLOCK, //only available on request (=> requestServerVariables) - VIRTUALSERVER_CLIENT_CONNECTIONS, //only available on request (=> requestServerVariables) - VIRTUALSERVER_QUERY_CLIENT_CONNECTIONS, //only available on request (=> requestServerVariables) - VIRTUALSERVER_HOSTBUTTON_TOOLTIP, //available when connected, always up-to-date - VIRTUALSERVER_HOSTBUTTON_URL, //available when connected, always up-to-date - VIRTUALSERVER_HOSTBUTTON_GFX_URL, //available when connected, always up-to-date - VIRTUALSERVER_QUERYCLIENTS_ONLINE, //only available on request (=> requestServerVariables) - VIRTUALSERVER_DOWNLOAD_QUOTA, //only available on request (=> requestServerVariables) - VIRTUALSERVER_UPLOAD_QUOTA, //only available on request (=> requestServerVariables) - VIRTUALSERVER_MONTH_BYTES_DOWNLOADED, //only available on request (=> requestServerVariables) - VIRTUALSERVER_MONTH_BYTES_UPLOADED, //only available on request (=> requestServerVariables) - VIRTUALSERVER_TOTAL_BYTES_DOWNLOADED, //only available on request (=> requestServerVariables) - VIRTUALSERVER_TOTAL_BYTES_UPLOADED, //only available on request (=> requestServerVariables) - VIRTUALSERVER_PORT, //only available on request (=> requestServerVariables) - VIRTUALSERVER_AUTOSTART, //only available on request (=> requestServerVariables) - VIRTUALSERVER_MACHINE_ID, //only available on request (=> requestServerVariables) - VIRTUALSERVER_NEEDED_IDENTITY_SECURITY_LEVEL, //only available on request (=> requestServerVariables) - VIRTUALSERVER_LOG_CLIENT, //only available on request (=> requestServerVariables) - VIRTUALSERVER_LOG_QUERY, //only available on request (=> requestServerVariables) - VIRTUALSERVER_LOG_CHANNEL, //only available on request (=> requestServerVariables) - VIRTUALSERVER_LOG_PERMISSIONS, //only available on request (=> requestServerVariables) - VIRTUALSERVER_LOG_SERVER, //only available on request (=> requestServerVariables) - VIRTUALSERVER_LOG_FILETRANSFER, //only available on request (=> requestServerVariables) - VIRTUALSERVER_MIN_CLIENT_VERSION, //only available on request (=> requestServerVariables) - VIRTUALSERVER_NAME_PHONETIC, //available when connected, always up-to-date - VIRTUALSERVER_ICON_ID, //available when connected, always up-to-date - VIRTUALSERVER_RESERVED_SLOTS, //available when connected, always up-to-date - VIRTUALSERVER_TOTAL_PACKETLOSS_SPEECH, //only available on request (=> requestServerVariables) - VIRTUALSERVER_TOTAL_PACKETLOSS_KEEPALIVE, //only available on request (=> requestServerVariables) - VIRTUALSERVER_TOTAL_PACKETLOSS_CONTROL, //only available on request (=> requestServerVariables) - VIRTUALSERVER_TOTAL_PACKETLOSS_TOTAL, //only available on request (=> requestServerVariables) - VIRTUALSERVER_TOTAL_PING, //only available on request (=> requestServerVariables) - VIRTUALSERVER_HOST, //internal use | contains comma separated ip list - VIRTUALSERVER_WEBLIST_ENABLED, //only available on request (=> requestServerVariables) - VIRTUALSERVER_AUTOGENERATED_PRIVILEGEKEY, //internal use - VIRTUALSERVER_ASK_FOR_PRIVILEGEKEY, //available when connected - VIRTUALSERVER_HOSTBANNER_MODE, //available when connected, always up-to-date - VIRTUALSERVER_CHANNEL_TEMP_DELETE_DELAY_DEFAULT, //available when connected, always up-to-date - VIRTUALSERVER_MIN_ANDROID_VERSION, //only available on request (=> requestServerVariables) - VIRTUALSERVER_MIN_IOS_VERSION, //only available on request (=> requestServerVariables) - VIRTUALSERVER_MIN_WINPHONE_VERSION, //only available on request (=> requestServerVariables) - - VIRTUALSERVER_LAST_CLIENT_CONNECT, - VIRTUALSERVER_LAST_QUERY_CONNECT, - VIRTUALSERVER_LAST_CLIENT_DISCONNECT, - VIRTUALSERVER_LAST_QUERY_DISCONNECT, - - VIRTUALSERVER_WEB_HOST, - VIRTUALSERVER_WEB_PORT, - - VIRTUALSERVER_DEFAULT_CLIENT_DESCRIPTION, - VIRTUALSERVER_DEFAULT_CHANNEL_DESCRIPTION, - VIRTUALSERVER_DEFAULT_CHANNEL_TOPIC, - - VIRTUALSERVER_MUSIC_BOT_LIMIT, - VIRTUALSERVER_SPOKEN_TIME, - VIRTUALSERVER_DISABLE_IP_SAVING, - - VIRTUALSERVER_COUNTRY_CODE, - - VIRTUALSERVER_ENDMARKER - }; - - enum ChannelProperties { - CHANNEL_UNDEFINED, - CHANNEL_BEGINMARKER, - CHANNEL_ID = CHANNEL_BEGINMARKER, - CHANNEL_PID, - CHANNEL_NAME, //Available for all channels that are "in view", always up-to-date - CHANNEL_TOPIC, //Available for all channels that are "in view", always up-to-date - CHANNEL_DESCRIPTION, //Must be requested (=> requestChannelDescription) - CHANNEL_PASSWORD, //not available manager side - CHANNEL_CODEC, //Available for all channels that are "in view", always up-to-date - CHANNEL_CODEC_QUALITY, //Available for all channels that are "in view", always up-to-date - CHANNEL_MAXCLIENTS, //Available for all channels that are "in view", always up-to-date - CHANNEL_MAXFAMILYCLIENTS, //Available for all channels that are "in view", always up-to-date - CHANNEL_ORDER, //Available for all channels that are "in view", always up-to-date - CHANNEL_FLAG_PERMANENT, //Available for all channels that are "in view", always up-to-date - CHANNEL_FLAG_SEMI_PERMANENT, //Available for all channels that are "in view", always up-to-date - CHANNEL_FLAG_DEFAULT, //Available for all channels that are "in view", always up-to-date - CHANNEL_FLAG_PASSWORD, //Available for all channels that are "in view", always up-to-date - CHANNEL_CODEC_LATENCY_FACTOR, //Available for all channels that are "in view", always up-to-date - CHANNEL_CODEC_IS_UNENCRYPTED, //Available for all channels that are "in view", always up-to-date - CHANNEL_SECURITY_SALT, //Not available manager side, not used in teamspeak, only SDK. Sets the options+salt for security hash. - CHANNEL_DELETE_DELAY, //How many seconds to wait before deleting this channel - CHANNEL_FLAG_MAXCLIENTS_UNLIMITED, //Available for all channels that are "in view", always up-to-date - CHANNEL_FLAG_MAXFAMILYCLIENTS_UNLIMITED,//Available for all channels that are "in view", always up-to-date - CHANNEL_FLAG_MAXFAMILYCLIENTS_INHERITED,//Available for all channels that are "in view", always up-to-date - CHANNEL_FLAG_ARE_SUBSCRIBED, //Only available manager side, stores whether we are subscribed to this channel - CHANNEL_FILEPATH, //not available manager side, the folder used for file-transfers for this channel - CHANNEL_NEEDED_TALK_POWER, //Available for all channels that are "in view", always up-to-date - CHANNEL_FORCED_SILENCE, //Available for all channels that are "in view", always up-to-date - CHANNEL_NAME_PHONETIC, //Available for all channels that are "in view", always up-to-date - CHANNEL_ICON_ID, //Available for all channels that are "in view", always up-to-date - CHANNEL_FLAG_PRIVATE, //Available for all channels that are "in view", always up-to-date - - CHANNEL_LAST_LEFT, - CHANNEL_CREATED_AT, - CHANNEL_CREATED_BY, - - CHANNEL_CONVERSATION_HISTORY_LENGTH, - CHANNEL_FLAG_CONVERSATION_PRIVATE, - - CHANNEL_ENDMARKER - }; - - enum GroupProperties { - GROUP_UNDEFINED, - GROUP_BEGINMARKER, - GROUP_ID = GROUP_BEGINMARKER, - GROUP_TYPE, - GROUP_NAME, - GROUP_SORTID, - GROUP_SAVEDB, - GROUP_NAMEMODE, - GROUP_ICONID, - GROUP_ENDMARKER - }; - - enum ClientProperties { - CLIENT_UNDEFINED, - CLIENT_BEGINMARKER, - CLIENT_UNIQUE_IDENTIFIER = CLIENT_BEGINMARKER, //automatically up-to-date for any manager "in view", can be used to identify this particular manager installation - CLIENT_NICKNAME, //automatically up-to-date for any manager "in view" - CLIENT_VERSION, //for other clients than ourself, this needs to be requested (=> requestClientVariables) - CLIENT_PLATFORM, //for other clients than ourself, this needs to be requested (=> requestClientVariables) - CLIENT_FLAG_TALKING, //automatically up-to-date for any manager that can be heard (in room / whisper) - CLIENT_INPUT_MUTED, //automatically up-to-date for any manager "in view", this clients microphone mute status - CLIENT_OUTPUT_MUTED, //automatically up-to-date for any manager "in view", this clients headphones/speakers/mic combined mute status - CLIENT_OUTPUTONLY_MUTED, //automatically up-to-date for any manager "in view", this clients headphones/speakers only mute status - CLIENT_INPUT_HARDWARE, //automatically up-to-date for any manager "in view", this clients microphone hardware status (is the capture device opened?) - CLIENT_OUTPUT_HARDWARE, //automatically up-to-date for any manager "in view", this clients headphone/speakers hardware status (is the playback device opened?) - CLIENT_DEFAULT_CHANNEL, //only usable for ourself, the default channel we used to connect on our last connection attempt - CLIENT_DEFAULT_CHANNEL_PASSWORD, //internal use - CLIENT_SERVER_PASSWORD, //internal use - CLIENT_META_DATA, //automatically up-to-date for any manager "in view", not used by TeamSpeak, free storage for sdk users - CLIENT_IS_RECORDING, //automatically up-to-date for any manager "in view" - CLIENT_VERSION_SIGN, //sign - CLIENT_SECURITY_HASH, //SDK use, not used by teamspeak. Hash is provided by an outside source. A channel will use the security salt + other manager data to calculate a hash, which must be the same as the one provided here. - - //Rare properties - CLIENT_KEY_OFFSET, //internal use - CLIENT_LOGIN_NAME, //used for serverquery clients, makes no sense on normal clients currently - CLIENT_LOGIN_PASSWORD, //used for serverquery clients, makes no sense on normal clients currently - CLIENT_DATABASE_ID, //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, holds database manager id - CLIENT_ID, //clid! - CLIENT_HARDWARE_ID, //hwid! - CLIENT_CHANNEL_GROUP_ID, //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, holds database manager id - CLIENT_SERVERGROUPS, //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, holds all servergroups manager belongs too - CLIENT_CREATED, //this needs to be requested (=> requestClientVariables), first time this manager connected to this server - CLIENT_LASTCONNECTED, //this needs to be requested (=> requestClientVariables), last time this manager connected to this server - CLIENT_TOTALCONNECTIONS, //this needs to be requested (=> requestClientVariables), how many times this manager connected to this server - CLIENT_AWAY, //automatically up-to-date for any manager "in view", this clients away status - CLIENT_AWAY_MESSAGE, //automatically up-to-date for any manager "in view", this clients away message - CLIENT_TYPE, //automatically up-to-date for any manager "in view", determines if this is a real manager or a server-query connection - CLIENT_TYPE_EXACT, //automatically up-to-date for any manager "in view", determines if this is a real manager or a server-query connection - CLIENT_FLAG_AVATAR, //automatically up-to-date for any manager "in view", this manager got an avatar - CLIENT_TALK_POWER, //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, holds database manager id - CLIENT_TALK_REQUEST, //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, holds timestamp where manager requested to talk - CLIENT_TALK_REQUEST_MSG, //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, holds matter for the request - CLIENT_DESCRIPTION, //automatically up-to-date for any manager "in view" - CLIENT_IS_TALKER, //automatically up-to-date for any manager "in view" - CLIENT_MONTH_BYTES_UPLOADED, //this needs to be requested (=> requestClientVariables) - CLIENT_MONTH_BYTES_DOWNLOADED, //this needs to be requested (=> requestClientVariables) - CLIENT_TOTAL_BYTES_UPLOADED, //this needs to be requested (=> requestClientVariables) - CLIENT_TOTAL_BYTES_DOWNLOADED, //this needs to be requested (=> requestClientVariables) - CLIENT_TOTAL_ONLINE_TIME, - CLIENT_MONTH_ONLINE_TIME, - CLIENT_IS_PRIORITY_SPEAKER, //automatically up-to-date for any manager "in view" - CLIENT_UNREAD_MESSAGES, //automatically up-to-date for any manager "in view" - CLIENT_NICKNAME_PHONETIC, //automatically up-to-date for any manager "in view" - CLIENT_NEEDED_SERVERQUERY_VIEW_POWER, //automatically up-to-date for any manager "in view" - CLIENT_DEFAULT_TOKEN, //only usable for ourself, the default token we used to connect on our last connection attempt - CLIENT_ICON_ID, //automatically up-to-date for any manager "in view" - CLIENT_IS_CHANNEL_COMMANDER, //automatically up-to-date for any manager "in view" - CLIENT_COUNTRY, //automatically up-to-date for any manager "in view" - CLIENT_CHANNEL_GROUP_INHERITED_CHANNEL_ID, //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, contains channel_id where the channel_group_id is set from - CLIENT_BADGES, //automatically up-to-date for any manager "in view", stores icons for partner badges - - CLIENT_MYTEAMSPEAK_ID, - CLIENT_INTEGRATIONS, - CLIENT_ACTIVE_INTEGRATIONS_INFO, - - //Music bot stuff - CLIENT_BOT_TYPE, - CLIENT_OWNER, - CLIENT_PLAYER_VOLUME, - CLIENT_LAST_CHANNEL, - CLIENT_PLAYER_STATE, - CLIENT_PLAYLIST_ID, - CLIENT_DISABLED, - CLIENT_UPTIME_MODE, - CLIENT_FLAG_NOTIFY_SONG_CHANGE, - - CLIENT_TEAFORO_ID, - CLIENT_TEAFORO_NAME, - CLIENT_TEAFORO_FLAGS, - - CLIENT_ENDMARKER - }; - - enum ConnectionProperties { - CONNECTION_UNDEFINED, - CONNECTION_BEGINMARKER, - CONNECTION_PING = CONNECTION_BEGINMARKER, //average latency for a round trip through and back this connection - CONNECTION_PING_DEVIATION, //standard deviation of the above average latency - CONNECTION_CONNECTED_TIME, //how long the connection exists already - CONNECTION_IDLE_TIME, //how long since the last action of this manager - CONNECTION_CLIENT_IP, //NEED DB SAVE! //IP of this manager (as seen from the server side) - CONNECTION_CLIENT_PORT, //Port of this manager (as seen from the server side) - CONNECTION_SERVER_IP, //IP of the server (seen from the manager side) - only available on yourself, not for remote clients, not available server side - CONNECTION_SERVER_PORT, //Port of the server (seen from the manager side) - only available on yourself, not for remote clients, not available server side - CONNECTION_PACKETS_SENT_SPEECH, //how many Speech packets were sent through this connection - CONNECTION_PACKETS_SENT_KEEPALIVE, - CONNECTION_PACKETS_SENT_CONTROL, - CONNECTION_PACKETS_SENT_TOTAL, //how many packets were sent totally (this is PACKETS_SENT_SPEECH + PACKETS_SENT_KEEPALIVE + PACKETS_SENT_CONTROL) - CONNECTION_BYTES_SENT_SPEECH, - CONNECTION_BYTES_SENT_KEEPALIVE, - CONNECTION_BYTES_SENT_CONTROL, - CONNECTION_BYTES_SENT_TOTAL, - CONNECTION_PACKETS_RECEIVED_SPEECH, - CONNECTION_PACKETS_RECEIVED_KEEPALIVE, - CONNECTION_PACKETS_RECEIVED_CONTROL, - CONNECTION_PACKETS_RECEIVED_TOTAL, - CONNECTION_BYTES_RECEIVED_SPEECH, - CONNECTION_BYTES_RECEIVED_KEEPALIVE, - CONNECTION_BYTES_RECEIVED_CONTROL, - CONNECTION_BYTES_RECEIVED_TOTAL, - CONNECTION_PACKETLOSS_SPEECH, - CONNECTION_PACKETLOSS_KEEPALIVE, - CONNECTION_PACKETLOSS_CONTROL, - CONNECTION_PACKETLOSS_TOTAL, //the probability with which a packet round trip failed because a packet was lost - CONNECTION_SERVER2CLIENT_PACKETLOSS_SPEECH, //the probability with which a speech packet failed from the server to the manager - CONNECTION_SERVER2CLIENT_PACKETLOSS_KEEPALIVE, - CONNECTION_SERVER2CLIENT_PACKETLOSS_CONTROL, - CONNECTION_SERVER2CLIENT_PACKETLOSS_TOTAL, - CONNECTION_CLIENT2SERVER_PACKETLOSS_SPEECH, - CONNECTION_CLIENT2SERVER_PACKETLOSS_KEEPALIVE, - CONNECTION_CLIENT2SERVER_PACKETLOSS_CONTROL, - CONNECTION_CLIENT2SERVER_PACKETLOSS_TOTAL, - CONNECTION_BANDWIDTH_SENT_LAST_SECOND_SPEECH, //howmany bytes of speech packets we sent during the last second - CONNECTION_BANDWIDTH_SENT_LAST_SECOND_KEEPALIVE, - CONNECTION_BANDWIDTH_SENT_LAST_SECOND_CONTROL, - CONNECTION_BANDWIDTH_SENT_LAST_SECOND_TOTAL, - CONNECTION_BANDWIDTH_SENT_LAST_MINUTE_SPEECH, //howmany bytes/s of speech packets we sent in average during the last minute - CONNECTION_BANDWIDTH_SENT_LAST_MINUTE_KEEPALIVE, - CONNECTION_BANDWIDTH_SENT_LAST_MINUTE_CONTROL, - CONNECTION_BANDWIDTH_SENT_LAST_MINUTE_TOTAL, - CONNECTION_BANDWIDTH_RECEIVED_LAST_SECOND_SPEECH, - CONNECTION_BANDWIDTH_RECEIVED_LAST_SECOND_KEEPALIVE, - CONNECTION_BANDWIDTH_RECEIVED_LAST_SECOND_CONTROL, - CONNECTION_BANDWIDTH_RECEIVED_LAST_SECOND_TOTAL, - CONNECTION_BANDWIDTH_RECEIVED_LAST_MINUTE_SPEECH, - CONNECTION_BANDWIDTH_RECEIVED_LAST_MINUTE_KEEPALIVE, - CONNECTION_BANDWIDTH_RECEIVED_LAST_MINUTE_CONTROL, - CONNECTION_BANDWIDTH_RECEIVED_LAST_MINUTE_TOTAL, - - //Rare properties - CONNECTION_FILETRANSFER_BANDWIDTH_SENT, //how many bytes per second are currently being sent by file transfers - CONNECTION_FILETRANSFER_BANDWIDTH_RECEIVED, //how many bytes per second are currently being received by file transfers - - CONNECTION_FILETRANSFER_BYTES_RECEIVED_TOTAL, //how many bytes we received in total through file transfers - CONNECTION_FILETRANSFER_BYTES_SENT_TOTAL, //how many bytes we sent in total through file transfers - - CONNECTION_ENDMARKER - }; - - enum PlaylistProperties { - PLAYLIST_UNDEFINED, - PLAYLIST_BEGINMARKER, - - PLAYLIST_ID = PLAYLIST_BEGINMARKER, - PLAYLIST_TITLE, - PLAYLIST_DESCRIPTION, - PLAYLIST_TYPE, - - PLAYLIST_OWNER_DBID, - PLAYLIST_OWNER_NAME, - - PLAYLIST_MAX_SONGS, - PLAYLIST_FLAG_DELETE_PLAYED, - PLAYLIST_FLAG_FINISHED, - PLAYLIST_REPLAY_MODE, /* 0 = normal | 1 = loop list | 2 = loop entry | 3 = shuffle */ - - PLAYLIST_CURRENT_SONG_ID, - - PLAYLIST_ENDMARKER - }; - - /* - enum PlayList { - PLAYLIST_OWNER, - PLAYLIST_NAME, - PLAYLIST_REPEAT_MODE, - PLAYLIST_DELETE_PLAYED_SONGS - }; - */ - - class PropertyDescription; - namespace impl { - template - extern std::deque> list(); - extern std::deque> list_all(); - - template - extern const std::shared_ptr &info(T /* property */); - - template - extern const std::shared_ptr &info(const std::string& /* key */); - - - extern const std::shared_ptr &info_key(const std::string &); - extern const std::shared_ptr &info_key(PropertyType, const std::string &); - extern const std::shared_ptr &info(PropertyType, int); - - template - inline PropertyType type() { - std::cerr << "[CRITICAL] Invalid property type!" << std::endl; - return PropertyType::PROP_TYPE_UNKNOWN; - } - - template<> - constexpr inline PropertyType type() { return PropertyType::PROP_TYPE_SERVER; } - - template<> - constexpr inline PropertyType type() { return PropertyType::PROP_TYPE_CHANNEL; } - - template<> - constexpr inline PropertyType type() { return PropertyType::PROP_TYPE_CLIENT; } - - template<> - constexpr inline PropertyType type() { return PropertyType::PROP_TYPE_CONNECTION; } - - template<> - constexpr inline PropertyType type() { return PropertyType::PROP_TYPE_GROUP; } - - template<> - constexpr inline PropertyType type() { return PropertyType::PROP_TYPE_INSTANCE; } - - template<> - constexpr inline PropertyType type() { return PropertyType::PROP_TYPE_PLAYLIST; } - - template<> - constexpr inline PropertyType type() { return PropertyType::PROP_TYPE_UNKNOWN; } - - inline size_t length(PropertyType type) { - switch (type) { - case PROP_TYPE_SERVER: - return VIRTUALSERVER_ENDMARKER - VIRTUALSERVER_BEGINMARKER; - case PROP_TYPE_CHANNEL: - return CHANNEL_ENDMARKER - CHANNEL_BEGINMARKER; - case PROP_TYPE_CLIENT: - return CLIENT_ENDMARKER - CLIENT_BEGINMARKER; - case PROP_TYPE_CONNECTION: - return CONNECTION_ENDMARKER - CONNECTION_BEGINMARKER; - case PROP_TYPE_GROUP: - return GROUP_ENDMARKER - GROUP_BEGINMARKER; - case PROP_TYPE_INSTANCE: - return SERVERINSTANCE_ENDMARKER - SERVERINSTANCE_BEGINMARKER; - case PROP_TYPE_PLAYLIST: - return PLAYLIST_ENDMARKER - PLAYLIST_BEGINMARKER; - case PROP_TYPE_UNKNOWN: - return UNKNOWN_ENDMARKER - UNKNOWN_BEGINMARKER; - default: - return 0; - } - } - - inline size_t offset(PropertyType type) { - switch (type) { - case PROP_TYPE_SERVER: - return VIRTUALSERVER_BEGINMARKER; - case PROP_TYPE_CHANNEL: - return CHANNEL_BEGINMARKER; - case PROP_TYPE_CLIENT: - return CLIENT_BEGINMARKER; - case PROP_TYPE_CONNECTION: - return CONNECTION_BEGINMARKER; - case PROP_TYPE_GROUP: - return GROUP_BEGINMARKER; - case PROP_TYPE_INSTANCE: - return SERVERINSTANCE_BEGINMARKER; - case PROP_TYPE_PLAYLIST: - return PLAYLIST_BEGINMARKER; - case PROP_TYPE_UNKNOWN: - return UNKNOWN_BEGINMARKER; - default: - return 0; - } - } - - extern bool validateUnique(); - - extern bool validateInput(const std::string &, ValueType); - } - - - template - inline const std::shared_ptr &info(T property) { return impl::info(property); } - - template - inline const std::shared_ptr &info(const std::string& key) { return impl::info(key); } - - class PropertyDescription { - public: - static std::shared_ptr unknown; - - std::string name; - std::string default_value; - - ValueType type_value = property::ValueType::TYPE_UNKNOWN; - PropertyType type_property = PropertyType::PROP_TYPE_UNKNOWN; - - int property_index = 0; - flag_type flags = 0; - - PropertyDescription(int property_id, PropertyType property_type, const std::string &name, const std::string &default_value, property::ValueType type, flag_type flags) noexcept; - - template - PropertyDescription(T property, const std::string &name, const std::string &default_value, property::ValueType type, flag_type flags) noexcept : PropertyDescription((int) property, impl::type(), name, default_value, type, flags) {} - - inline bool operator==(const PropertyDescription& other) const { - return other.property_index == this->property_index && other.type_property == this->type_property; - } - - inline bool operator==(const std::shared_ptr& other) const { - return this->operator==(*other); - } - - template ::value, int>::type = 0> - inline bool operator==(const T& type) const { - return this->property_index == type && impl::type() == this->type_property; - } - - inline bool validate_input(const std::string& input) { - return impl::validateInput(input, this->type_value); - } - }; + enum PropertyType { + PROP_TYPE_SERVER = 0, + PROP_TYPE_CHANNEL = 1, + PROP_TYPE_GROUP = 2, + PROP_TYPE_CLIENT = 3, + PROP_TYPE_INSTANCE = 4, + PROP_TYPE_CONNECTION = 5, + PROP_TYPE_PLAYLIST = 6, + PROP_TYPE_UNKNOWN = 7 + }; + static constexpr const char *PropertyType_Names[7] = { + "SERVER", + "CHANNEL", + "GROUP", + "CLIENT", + "INSTANCE", + "CONNECTION", + "UNKNOWN" + }; + + enum ValueType { + TYPE_UNKNOWN, + TYPE_STRING, + TYPE_BOOL, + TYPE_SIGNED_NUMBER, + TYPE_UNSIGNED_NUMBER, + TYPE_FLOAT + }; + + typedef uint32_t flag_type; + enum flag : flag_type { + FLAG_BEGIN = 0b1, + FLAG_INTERNAL = FLAG_BEGIN << 1UL, //Just for internal usage + FLAG_GLOBAL = FLAG_INTERNAL << 1UL, //Not server bound + FLAG_SNAPSHOT = FLAG_GLOBAL << 1UL, //Saved within snapshots + FLAG_SAVE = FLAG_SNAPSHOT << 1UL, //Saved to database + FLAG_SAVE_MUSIC = FLAG_SAVE << 1UL, //Saved to database + FLAG_NEW = FLAG_SAVE_MUSIC << 1UL, //Its a non TeamSpeak property + FLAG_SERVER_VARIABLE = FLAG_NEW << 1UL, + FLAG_SERVER_VIEW = FLAG_SERVER_VARIABLE << 1UL, + FLAG_CLIENT_VARIABLE = FLAG_SERVER_VIEW << 1UL, + FLAG_CLIENT_VIEW = FLAG_CLIENT_VARIABLE << 1UL, + FLAG_CLIENT_INFO = FLAG_CLIENT_VIEW << 1UL, + FLAG_CHANNEL_VARIABLE = FLAG_CLIENT_INFO << 1UL, + FLAG_CHANNEL_VIEW = FLAG_CHANNEL_VARIABLE << 1UL, + FLAG_GROUP_VIEW = FLAG_CHANNEL_VIEW << 1UL, + FLAG_INSTANCE_VARIABLE = FLAG_GROUP_VIEW << 1UL, + FLAG_USER_EDITABLE = FLAG_INSTANCE_VARIABLE << 1UL, + FLAG_PLAYLIST_VARIABLE = FLAG_USER_EDITABLE << 1UL, + }; + static constexpr const char *flag_names[sizeof(flag) * 8] = + {"UNDEFINED", "FLAG_INTERNAL", "FLAG_GLOBAL", "FLAG_SNAPSHOT", "FLAG_SAVE", "FLAG_SAVE_MUSIC", "FLAG_NEW", + "FLAG_SERVER_VARIABLE", "FLAG_SERVER_VIEW", "FLAG_CLIENT_VARIABLE", "FLAG_CLIENT_VIEW", "FLAG_CLIENT_INFO", + "FLAG_CHANNEL_VARIABLE", "FLAG_CHANNEL_VIEW", "FLAG_GROUP_VIEW", "FLAG_INSTANCE_VARIABLE", "FLAG_USER_EDITABLE","FLAG_PLAYLIST_VARIABLE"}; + + enum UnknownProperties { + UNKNOWN_UNDEFINED, + UNKNOWN_BEGINMARKER, + UNKNOWN_ENDMARKER = UNKNOWN_BEGINMARKER + }; + + enum InstanceProperties { + SERVERINSTANCE_UNDEFINED, + SERVERINSTANCE_BEGINMARKER, + SERVERINSTANCE_DATABASE_VERSION = SERVERINSTANCE_BEGINMARKER, + SERVERINSTANCE_PERMISSIONS_VERSION, + + SERVERINSTANCE_FILETRANSFER_HOST, + SERVERINSTANCE_FILETRANSFER_PORT, + SERVERINSTANCE_FILETRANSFER_MAX_CONNECTIONS, + SERVERINSTANCE_FILETRANSFER_MAX_CONNECTIONS_PER_IP, + + SERVERINSTANCE_QUERY_HOST, + SERVERINSTANCE_QUERY_PORT, + SERVERINSTANCE_QUERY_MAX_CONNECTIONS, + SERVERINSTANCE_QUERY_MAX_CONNECTIONS_PER_IP, + + SERVERINSTANCE_MONTHLY_TIMESTAMP, + SERVERINSTANCE_MAX_DOWNLOAD_TOTAL_BANDWIDTH, + SERVERINSTANCE_MAX_UPLOAD_TOTAL_BANDWIDTH, + SERVERINSTANCE_SERVERQUERY_FLOOD_COMMANDS, //how many commands we can issue while in the SERVERINSTANCE_SERVERQUERY_FLOOD_TIME window + SERVERINSTANCE_SERVERQUERY_FLOOD_TIME, //time window in seconds for max command execution check + SERVERINSTANCE_SERVERQUERY_BAN_TIME, //how many seconds someone get banned if he floods + SERVERINSTANCE_TEMPLATE_SERVERADMIN_GROUP, + SERVERINSTANCE_TEMPLATE_SERVERDEFAULT_GROUP, + SERVERINSTANCE_TEMPLATE_CHANNELADMIN_GROUP, + SERVERINSTANCE_TEMPLATE_CHANNELDEFAULT_GROUP, + SERVERINSTANCE_TEMPLATE_MUSICDEFAULT_GROUP, + SERVERINSTANCE_GUEST_SERVERQUERY_GROUP, + SERVERINSTANCE_ADMIN_SERVERQUERY_GROUP, + SERVERINSTANCE_PENDING_CONNECTIONS_PER_IP, + SERVERINSTANCE_SPOKEN_TIME_TOTAL, + SERVERINSTANCE_SPOKEN_TIME_DELETED, + SERVERINSTANCE_SPOKEN_TIME_ALIVE, + SERVERINSTANCE_SPOKEN_TIME_VARIANZ, + + SERVERINSTANCE_VIRTUAL_SERVER_ID_INDEX, + + SERVERINSTANCE_UNIQUE_ID, + SERVERINSTANCE_ENDMARKER, + }; + + enum VirtualServerProperties { + VIRTUALSERVER_UNDEFINED = 0, + VIRTUALSERVER_BEGINMARKER, + VIRTUALSERVER_UNIQUE_IDENTIFIER = VIRTUALSERVER_BEGINMARKER, //available when connected, can be used to identify this particular server installation + VIRTUALSERVER_NAME, //available and always up-to-date when connected + VIRTUALSERVER_WELCOMEMESSAGE, //available when connected, (=> requestServerVariables) + VIRTUALSERVER_PLATFORM, //available when connected + VIRTUALSERVER_VERSION, //available when connected + VIRTUALSERVER_MAXCLIENTS, //only available on request (=> requestServerVariables), stores the maximum number of clients that may currently join the server + VIRTUALSERVER_PASSWORD, //not available to clients, the server password + VIRTUALSERVER_CLIENTS_ONLINE, //only available on request (=> requestServerVariables), + VIRTUALSERVER_CHANNELS_ONLINE, //only available on request (=> requestServerVariables), + VIRTUALSERVER_CREATED, //available when connected, stores the time when the server was created + VIRTUALSERVER_UPTIME, //only available on request (=> requestServerVariables), the time since the server was started + VIRTUALSERVER_CODEC_ENCRYPTION_MODE, //available and always up-to-date when connected + + //Rare properties + VIRTUALSERVER_KEYPAIR, //internal use + VIRTUALSERVER_HOSTMESSAGE, //available when connected, not updated while connected + VIRTUALSERVER_HOSTMESSAGE_MODE, //available when connected, not updated while connected + VIRTUALSERVER_FILEBASE, //not available to clients, stores the folder used for file transfers + VIRTUALSERVER_DEFAULT_SERVER_GROUP, //the manager permissions server group that a new manager gets assigned + VIRTUALSERVER_DEFAULT_MUSIC_GROUP, //the manager permissions server group that a new manager gets assigned + VIRTUALSERVER_DEFAULT_CHANNEL_GROUP, //the channel permissions group that a new manager gets assigned when joining a channel + VIRTUALSERVER_FLAG_PASSWORD, //only available on request (=> requestServerVariables) + VIRTUALSERVER_DEFAULT_CHANNEL_ADMIN_GROUP, //the channel permissions group that a manager gets assigned when creating a channel + VIRTUALSERVER_MAX_DOWNLOAD_TOTAL_BANDWIDTH, //only available on request (=> requestServerVariables) + VIRTUALSERVER_MAX_UPLOAD_TOTAL_BANDWIDTH, //only available on request (=> requestServerVariables) + VIRTUALSERVER_HOSTBANNER_URL, //available when connected, always up-to-date + VIRTUALSERVER_HOSTBANNER_GFX_URL, //available when connected, always up-to-date + VIRTUALSERVER_HOSTBANNER_GFX_INTERVAL, //available when connected, always up-to-date + VIRTUALSERVER_COMPLAIN_AUTOBAN_COUNT, //only available on request (=> requestServerVariables) + VIRTUALSERVER_COMPLAIN_AUTOBAN_TIME, //only available on request (=> requestServerVariables) + VIRTUALSERVER_COMPLAIN_REMOVE_TIME, //only available on request (=> requestServerVariables) + VIRTUALSERVER_MIN_CLIENTS_IN_CHANNEL_BEFORE_FORCED_SILENCE,//only available on request (=> requestServerVariables) + VIRTUALSERVER_PRIORITY_SPEAKER_DIMM_MODIFICATOR, //available when connected, always up-to-date + VIRTUALSERVER_ID, //available when connected + VIRTUALSERVER_ANTIFLOOD_POINTS_TICK_REDUCE, //only available on request (=> requestServerVariables) + VIRTUALSERVER_ANTIFLOOD_POINTS_NEEDED_COMMAND_BLOCK, //only available on request (=> requestServerVariables) + VIRTUALSERVER_ANTIFLOOD_POINTS_NEEDED_IP_BLOCK, //only available on request (=> requestServerVariables) + VIRTUALSERVER_CLIENT_CONNECTIONS, //only available on request (=> requestServerVariables) + VIRTUALSERVER_QUERY_CLIENT_CONNECTIONS, //only available on request (=> requestServerVariables) + VIRTUALSERVER_HOSTBUTTON_TOOLTIP, //available when connected, always up-to-date + VIRTUALSERVER_HOSTBUTTON_URL, //available when connected, always up-to-date + VIRTUALSERVER_HOSTBUTTON_GFX_URL, //available when connected, always up-to-date + VIRTUALSERVER_QUERYCLIENTS_ONLINE, //only available on request (=> requestServerVariables) + VIRTUALSERVER_DOWNLOAD_QUOTA, //only available on request (=> requestServerVariables) + VIRTUALSERVER_UPLOAD_QUOTA, //only available on request (=> requestServerVariables) + VIRTUALSERVER_MONTH_BYTES_DOWNLOADED, //only available on request (=> requestServerVariables) + VIRTUALSERVER_MONTH_BYTES_UPLOADED, //only available on request (=> requestServerVariables) + VIRTUALSERVER_TOTAL_BYTES_DOWNLOADED, //only available on request (=> requestServerVariables) + VIRTUALSERVER_TOTAL_BYTES_UPLOADED, //only available on request (=> requestServerVariables) + VIRTUALSERVER_PORT, //only available on request (=> requestServerVariables) + VIRTUALSERVER_AUTOSTART, //only available on request (=> requestServerVariables) + VIRTUALSERVER_MACHINE_ID, //only available on request (=> requestServerVariables) + VIRTUALSERVER_NEEDED_IDENTITY_SECURITY_LEVEL, //only available on request (=> requestServerVariables) + VIRTUALSERVER_LOG_CLIENT, //only available on request (=> requestServerVariables) + VIRTUALSERVER_LOG_QUERY, //only available on request (=> requestServerVariables) + VIRTUALSERVER_LOG_CHANNEL, //only available on request (=> requestServerVariables) + VIRTUALSERVER_LOG_PERMISSIONS, //only available on request (=> requestServerVariables) + VIRTUALSERVER_LOG_SERVER, //only available on request (=> requestServerVariables) + VIRTUALSERVER_LOG_FILETRANSFER, //only available on request (=> requestServerVariables) + VIRTUALSERVER_MIN_CLIENT_VERSION, //only available on request (=> requestServerVariables) + VIRTUALSERVER_NAME_PHONETIC, //available when connected, always up-to-date + VIRTUALSERVER_ICON_ID, //available when connected, always up-to-date + VIRTUALSERVER_RESERVED_SLOTS, //available when connected, always up-to-date + VIRTUALSERVER_TOTAL_PACKETLOSS_SPEECH, //only available on request (=> requestServerVariables) + VIRTUALSERVER_TOTAL_PACKETLOSS_KEEPALIVE, //only available on request (=> requestServerVariables) + VIRTUALSERVER_TOTAL_PACKETLOSS_CONTROL, //only available on request (=> requestServerVariables) + VIRTUALSERVER_TOTAL_PACKETLOSS_TOTAL, //only available on request (=> requestServerVariables) + VIRTUALSERVER_TOTAL_PING, //only available on request (=> requestServerVariables) + VIRTUALSERVER_HOST, //internal use | contains comma separated ip list + VIRTUALSERVER_WEBLIST_ENABLED, //only available on request (=> requestServerVariables) + VIRTUALSERVER_AUTOGENERATED_PRIVILEGEKEY, //internal use + VIRTUALSERVER_ASK_FOR_PRIVILEGEKEY, //available when connected + VIRTUALSERVER_HOSTBANNER_MODE, //available when connected, always up-to-date + VIRTUALSERVER_CHANNEL_TEMP_DELETE_DELAY_DEFAULT, //available when connected, always up-to-date + VIRTUALSERVER_MIN_ANDROID_VERSION, //only available on request (=> requestServerVariables) + VIRTUALSERVER_MIN_IOS_VERSION, //only available on request (=> requestServerVariables) + VIRTUALSERVER_MIN_WINPHONE_VERSION, //only available on request (=> requestServerVariables) + + VIRTUALSERVER_LAST_CLIENT_CONNECT, + VIRTUALSERVER_LAST_QUERY_CONNECT, + VIRTUALSERVER_LAST_CLIENT_DISCONNECT, + VIRTUALSERVER_LAST_QUERY_DISCONNECT, + + VIRTUALSERVER_WEB_HOST, + VIRTUALSERVER_WEB_PORT, + + VIRTUALSERVER_DEFAULT_CLIENT_DESCRIPTION, + VIRTUALSERVER_DEFAULT_CHANNEL_DESCRIPTION, + VIRTUALSERVER_DEFAULT_CHANNEL_TOPIC, + + VIRTUALSERVER_MUSIC_BOT_LIMIT, + VIRTUALSERVER_SPOKEN_TIME, + VIRTUALSERVER_DISABLE_IP_SAVING, + + VIRTUALSERVER_COUNTRY_CODE, + + VIRTUALSERVER_ENDMARKER + }; + + enum ChannelProperties { + CHANNEL_UNDEFINED, + CHANNEL_BEGINMARKER, + CHANNEL_ID = CHANNEL_BEGINMARKER, + CHANNEL_PID, + CHANNEL_NAME, //Available for all channels that are "in view", always up-to-date + CHANNEL_TOPIC, //Available for all channels that are "in view", always up-to-date + CHANNEL_DESCRIPTION, //Must be requested (=> requestChannelDescription) + CHANNEL_PASSWORD, //not available manager side + CHANNEL_CODEC, //Available for all channels that are "in view", always up-to-date + CHANNEL_CODEC_QUALITY, //Available for all channels that are "in view", always up-to-date + CHANNEL_MAXCLIENTS, //Available for all channels that are "in view", always up-to-date + CHANNEL_MAXFAMILYCLIENTS, //Available for all channels that are "in view", always up-to-date + CHANNEL_ORDER, //Available for all channels that are "in view", always up-to-date + CHANNEL_FLAG_PERMANENT, //Available for all channels that are "in view", always up-to-date + CHANNEL_FLAG_SEMI_PERMANENT, //Available for all channels that are "in view", always up-to-date + CHANNEL_FLAG_DEFAULT, //Available for all channels that are "in view", always up-to-date + CHANNEL_FLAG_PASSWORD, //Available for all channels that are "in view", always up-to-date + CHANNEL_CODEC_LATENCY_FACTOR, //Available for all channels that are "in view", always up-to-date + CHANNEL_CODEC_IS_UNENCRYPTED, //Available for all channels that are "in view", always up-to-date + CHANNEL_SECURITY_SALT, //Not available manager side, not used in teamspeak, only SDK. Sets the options+salt for security hash. + CHANNEL_DELETE_DELAY, //How many seconds to wait before deleting this channel + CHANNEL_FLAG_MAXCLIENTS_UNLIMITED, //Available for all channels that are "in view", always up-to-date + CHANNEL_FLAG_MAXFAMILYCLIENTS_UNLIMITED,//Available for all channels that are "in view", always up-to-date + CHANNEL_FLAG_MAXFAMILYCLIENTS_INHERITED,//Available for all channels that are "in view", always up-to-date + CHANNEL_FLAG_ARE_SUBSCRIBED, //Only available manager side, stores whether we are subscribed to this channel + CHANNEL_FILEPATH, //not available manager side, the folder used for file-transfers for this channel + CHANNEL_NEEDED_TALK_POWER, //Available for all channels that are "in view", always up-to-date + CHANNEL_FORCED_SILENCE, //Available for all channels that are "in view", always up-to-date + CHANNEL_NAME_PHONETIC, //Available for all channels that are "in view", always up-to-date + CHANNEL_ICON_ID, //Available for all channels that are "in view", always up-to-date + CHANNEL_FLAG_PRIVATE, //Available for all channels that are "in view", always up-to-date + + CHANNEL_LAST_LEFT, + CHANNEL_CREATED_AT, + CHANNEL_CREATED_BY, + + CHANNEL_CONVERSATION_HISTORY_LENGTH, + CHANNEL_FLAG_CONVERSATION_PRIVATE, + + CHANNEL_ENDMARKER + }; + + enum GroupProperties { + GROUP_UNDEFINED, + GROUP_BEGINMARKER, + GROUP_ID = GROUP_BEGINMARKER, + GROUP_TYPE, + GROUP_NAME, + GROUP_SORTID, + GROUP_SAVEDB, + GROUP_NAMEMODE, + GROUP_ICONID, + GROUP_ENDMARKER + }; + + enum ClientProperties { + CLIENT_UNDEFINED, + CLIENT_BEGINMARKER, + CLIENT_UNIQUE_IDENTIFIER = CLIENT_BEGINMARKER, //automatically up-to-date for any manager "in view", can be used to identify this particular manager installation + CLIENT_NICKNAME, //automatically up-to-date for any manager "in view" + CLIENT_VERSION, //for other clients than ourself, this needs to be requested (=> requestClientVariables) + CLIENT_PLATFORM, //for other clients than ourself, this needs to be requested (=> requestClientVariables) + CLIENT_FLAG_TALKING, //automatically up-to-date for any manager that can be heard (in room / whisper) + CLIENT_INPUT_MUTED, //automatically up-to-date for any manager "in view", this clients microphone mute status + CLIENT_OUTPUT_MUTED, //automatically up-to-date for any manager "in view", this clients headphones/speakers/mic combined mute status + CLIENT_OUTPUTONLY_MUTED, //automatically up-to-date for any manager "in view", this clients headphones/speakers only mute status + CLIENT_INPUT_HARDWARE, //automatically up-to-date for any manager "in view", this clients microphone hardware status (is the capture device opened?) + CLIENT_OUTPUT_HARDWARE, //automatically up-to-date for any manager "in view", this clients headphone/speakers hardware status (is the playback device opened?) + CLIENT_DEFAULT_CHANNEL, //only usable for ourself, the default channel we used to connect on our last connection attempt + CLIENT_DEFAULT_CHANNEL_PASSWORD, //internal use + CLIENT_SERVER_PASSWORD, //internal use + CLIENT_META_DATA, //automatically up-to-date for any manager "in view", not used by TeamSpeak, free storage for sdk users + CLIENT_IS_RECORDING, //automatically up-to-date for any manager "in view" + CLIENT_VERSION_SIGN, //sign + CLIENT_SECURITY_HASH, //SDK use, not used by teamspeak. Hash is provided by an outside source. A channel will use the security salt + other manager data to calculate a hash, which must be the same as the one provided here. + + //Rare properties + CLIENT_KEY_OFFSET, //internal use + CLIENT_LOGIN_NAME, //used for serverquery clients, makes no sense on normal clients currently + CLIENT_LOGIN_PASSWORD, //used for serverquery clients, makes no sense on normal clients currently + CLIENT_DATABASE_ID, //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, holds database manager id + CLIENT_ID, //clid! + CLIENT_HARDWARE_ID, //hwid! + CLIENT_CHANNEL_GROUP_ID, //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, holds database manager id + CLIENT_SERVERGROUPS, //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, holds all servergroups manager belongs too + CLIENT_CREATED, //this needs to be requested (=> requestClientVariables), first time this manager connected to this server + CLIENT_LASTCONNECTED, //this needs to be requested (=> requestClientVariables), last time this manager connected to this server + CLIENT_TOTALCONNECTIONS, //this needs to be requested (=> requestClientVariables), how many times this manager connected to this server + CLIENT_AWAY, //automatically up-to-date for any manager "in view", this clients away status + CLIENT_AWAY_MESSAGE, //automatically up-to-date for any manager "in view", this clients away message + CLIENT_TYPE, //automatically up-to-date for any manager "in view", determines if this is a real manager or a server-query connection + CLIENT_TYPE_EXACT, //automatically up-to-date for any manager "in view", determines if this is a real manager or a server-query connection + CLIENT_FLAG_AVATAR, //automatically up-to-date for any manager "in view", this manager got an avatar + CLIENT_TALK_POWER, //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, holds database manager id + CLIENT_TALK_REQUEST, //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, holds timestamp where manager requested to talk + CLIENT_TALK_REQUEST_MSG, //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, holds matter for the request + CLIENT_DESCRIPTION, //automatically up-to-date for any manager "in view" + CLIENT_IS_TALKER, //automatically up-to-date for any manager "in view" + CLIENT_MONTH_BYTES_UPLOADED, //this needs to be requested (=> requestClientVariables) + CLIENT_MONTH_BYTES_DOWNLOADED, //this needs to be requested (=> requestClientVariables) + CLIENT_TOTAL_BYTES_UPLOADED, //this needs to be requested (=> requestClientVariables) + CLIENT_TOTAL_BYTES_DOWNLOADED, //this needs to be requested (=> requestClientVariables) + CLIENT_TOTAL_ONLINE_TIME, + CLIENT_MONTH_ONLINE_TIME, + CLIENT_IS_PRIORITY_SPEAKER, //automatically up-to-date for any manager "in view" + CLIENT_UNREAD_MESSAGES, //automatically up-to-date for any manager "in view" + CLIENT_NICKNAME_PHONETIC, //automatically up-to-date for any manager "in view" + CLIENT_NEEDED_SERVERQUERY_VIEW_POWER, //automatically up-to-date for any manager "in view" + CLIENT_DEFAULT_TOKEN, //only usable for ourself, the default token we used to connect on our last connection attempt + CLIENT_ICON_ID, //automatically up-to-date for any manager "in view" + CLIENT_IS_CHANNEL_COMMANDER, //automatically up-to-date for any manager "in view" + CLIENT_COUNTRY, //automatically up-to-date for any manager "in view" + CLIENT_CHANNEL_GROUP_INHERITED_CHANNEL_ID, //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, contains channel_id where the channel_group_id is set from + CLIENT_BADGES, //automatically up-to-date for any manager "in view", stores icons for partner badges + + CLIENT_MYTEAMSPEAK_ID, + CLIENT_INTEGRATIONS, + CLIENT_ACTIVE_INTEGRATIONS_INFO, + + //Music bot stuff + CLIENT_BOT_TYPE, + CLIENT_OWNER, + CLIENT_PLAYER_VOLUME, + CLIENT_LAST_CHANNEL, + CLIENT_PLAYER_STATE, + CLIENT_PLAYLIST_ID, + CLIENT_DISABLED, + CLIENT_UPTIME_MODE, + CLIENT_FLAG_NOTIFY_SONG_CHANGE, + + CLIENT_TEAFORO_ID, + CLIENT_TEAFORO_NAME, + CLIENT_TEAFORO_FLAGS, + + CLIENT_ENDMARKER + }; + + enum ConnectionProperties { + CONNECTION_UNDEFINED, + CONNECTION_BEGINMARKER, + CONNECTION_PING = CONNECTION_BEGINMARKER, //average latency for a round trip through and back this connection + CONNECTION_PING_DEVIATION, //standard deviation of the above average latency + CONNECTION_CONNECTED_TIME, //how long the connection exists already + CONNECTION_IDLE_TIME, //how long since the last action of this manager + CONNECTION_CLIENT_IP, //NEED DB SAVE! //IP of this manager (as seen from the server side) + CONNECTION_CLIENT_PORT, //Port of this manager (as seen from the server side) + CONNECTION_SERVER_IP, //IP of the server (seen from the manager side) - only available on yourself, not for remote clients, not available server side + CONNECTION_SERVER_PORT, //Port of the server (seen from the manager side) - only available on yourself, not for remote clients, not available server side + CONNECTION_PACKETS_SENT_SPEECH, //how many Speech packets were sent through this connection + CONNECTION_PACKETS_SENT_KEEPALIVE, + CONNECTION_PACKETS_SENT_CONTROL, + CONNECTION_PACKETS_SENT_TOTAL, //how many packets were sent totally (this is PACKETS_SENT_SPEECH + PACKETS_SENT_KEEPALIVE + PACKETS_SENT_CONTROL) + CONNECTION_BYTES_SENT_SPEECH, + CONNECTION_BYTES_SENT_KEEPALIVE, + CONNECTION_BYTES_SENT_CONTROL, + CONNECTION_BYTES_SENT_TOTAL, + CONNECTION_PACKETS_RECEIVED_SPEECH, + CONNECTION_PACKETS_RECEIVED_KEEPALIVE, + CONNECTION_PACKETS_RECEIVED_CONTROL, + CONNECTION_PACKETS_RECEIVED_TOTAL, + CONNECTION_BYTES_RECEIVED_SPEECH, + CONNECTION_BYTES_RECEIVED_KEEPALIVE, + CONNECTION_BYTES_RECEIVED_CONTROL, + CONNECTION_BYTES_RECEIVED_TOTAL, + CONNECTION_PACKETLOSS_SPEECH, + CONNECTION_PACKETLOSS_KEEPALIVE, + CONNECTION_PACKETLOSS_CONTROL, + CONNECTION_PACKETLOSS_TOTAL, //the probability with which a packet round trip failed because a packet was lost + CONNECTION_SERVER2CLIENT_PACKETLOSS_SPEECH, //the probability with which a speech packet failed from the server to the manager + CONNECTION_SERVER2CLIENT_PACKETLOSS_KEEPALIVE, + CONNECTION_SERVER2CLIENT_PACKETLOSS_CONTROL, + CONNECTION_SERVER2CLIENT_PACKETLOSS_TOTAL, + CONNECTION_CLIENT2SERVER_PACKETLOSS_SPEECH, + CONNECTION_CLIENT2SERVER_PACKETLOSS_KEEPALIVE, + CONNECTION_CLIENT2SERVER_PACKETLOSS_CONTROL, + CONNECTION_CLIENT2SERVER_PACKETLOSS_TOTAL, + CONNECTION_BANDWIDTH_SENT_LAST_SECOND_SPEECH, //howmany bytes of speech packets we sent during the last second + CONNECTION_BANDWIDTH_SENT_LAST_SECOND_KEEPALIVE, + CONNECTION_BANDWIDTH_SENT_LAST_SECOND_CONTROL, + CONNECTION_BANDWIDTH_SENT_LAST_SECOND_TOTAL, + CONNECTION_BANDWIDTH_SENT_LAST_MINUTE_SPEECH, //howmany bytes/s of speech packets we sent in average during the last minute + CONNECTION_BANDWIDTH_SENT_LAST_MINUTE_KEEPALIVE, + CONNECTION_BANDWIDTH_SENT_LAST_MINUTE_CONTROL, + CONNECTION_BANDWIDTH_SENT_LAST_MINUTE_TOTAL, + CONNECTION_BANDWIDTH_RECEIVED_LAST_SECOND_SPEECH, + CONNECTION_BANDWIDTH_RECEIVED_LAST_SECOND_KEEPALIVE, + CONNECTION_BANDWIDTH_RECEIVED_LAST_SECOND_CONTROL, + CONNECTION_BANDWIDTH_RECEIVED_LAST_SECOND_TOTAL, + CONNECTION_BANDWIDTH_RECEIVED_LAST_MINUTE_SPEECH, + CONNECTION_BANDWIDTH_RECEIVED_LAST_MINUTE_KEEPALIVE, + CONNECTION_BANDWIDTH_RECEIVED_LAST_MINUTE_CONTROL, + CONNECTION_BANDWIDTH_RECEIVED_LAST_MINUTE_TOTAL, + + //Rare properties + CONNECTION_FILETRANSFER_BANDWIDTH_SENT, //how many bytes per second are currently being sent by file transfers + CONNECTION_FILETRANSFER_BANDWIDTH_RECEIVED, //how many bytes per second are currently being received by file transfers + + CONNECTION_FILETRANSFER_BYTES_RECEIVED_TOTAL, //how many bytes we received in total through file transfers + CONNECTION_FILETRANSFER_BYTES_SENT_TOTAL, //how many bytes we sent in total through file transfers + + CONNECTION_ENDMARKER + }; + + enum PlaylistProperties { + PLAYLIST_UNDEFINED, + PLAYLIST_BEGINMARKER, + + PLAYLIST_ID = PLAYLIST_BEGINMARKER, + PLAYLIST_TITLE, + PLAYLIST_DESCRIPTION, + PLAYLIST_TYPE, + + PLAYLIST_OWNER_DBID, + PLAYLIST_OWNER_NAME, + + PLAYLIST_MAX_SONGS, + PLAYLIST_FLAG_DELETE_PLAYED, + PLAYLIST_FLAG_FINISHED, + PLAYLIST_REPLAY_MODE, /* 0 = normal | 1 = loop list | 2 = loop entry | 3 = shuffle */ + + PLAYLIST_CURRENT_SONG_ID, + + PLAYLIST_ENDMARKER + }; + + /* + enum PlayList { + PLAYLIST_OWNER, + PLAYLIST_NAME, + PLAYLIST_REPEAT_MODE, + PLAYLIST_DELETE_PLAYED_SONGS + }; + */ + + class PropertyDescription; + namespace impl { + template + extern std::deque> list(); + extern std::deque> list_all(); + + template + extern const std::shared_ptr &info(T /* property */); + + template + extern const std::shared_ptr &info(const std::string& /* key */); + + + extern const std::shared_ptr &info_key(const std::string &); + extern const std::shared_ptr &info_key(PropertyType, const std::string &); + extern const std::shared_ptr &info(PropertyType, int); + + template + inline PropertyType type() { + std::cerr << "[CRITICAL] Invalid property type!" << std::endl; + return PropertyType::PROP_TYPE_UNKNOWN; + } + + template<> + constexpr inline PropertyType type() { return PropertyType::PROP_TYPE_SERVER; } + + template<> + constexpr inline PropertyType type() { return PropertyType::PROP_TYPE_CHANNEL; } + + template<> + constexpr inline PropertyType type() { return PropertyType::PROP_TYPE_CLIENT; } + + template<> + constexpr inline PropertyType type() { return PropertyType::PROP_TYPE_CONNECTION; } + + template<> + constexpr inline PropertyType type() { return PropertyType::PROP_TYPE_GROUP; } + + template<> + constexpr inline PropertyType type() { return PropertyType::PROP_TYPE_INSTANCE; } + + template<> + constexpr inline PropertyType type() { return PropertyType::PROP_TYPE_PLAYLIST; } + + template<> + constexpr inline PropertyType type() { return PropertyType::PROP_TYPE_UNKNOWN; } + + inline size_t length(PropertyType type) { + switch (type) { + case PROP_TYPE_SERVER: + return VIRTUALSERVER_ENDMARKER - VIRTUALSERVER_BEGINMARKER; + case PROP_TYPE_CHANNEL: + return CHANNEL_ENDMARKER - CHANNEL_BEGINMARKER; + case PROP_TYPE_CLIENT: + return CLIENT_ENDMARKER - CLIENT_BEGINMARKER; + case PROP_TYPE_CONNECTION: + return CONNECTION_ENDMARKER - CONNECTION_BEGINMARKER; + case PROP_TYPE_GROUP: + return GROUP_ENDMARKER - GROUP_BEGINMARKER; + case PROP_TYPE_INSTANCE: + return SERVERINSTANCE_ENDMARKER - SERVERINSTANCE_BEGINMARKER; + case PROP_TYPE_PLAYLIST: + return PLAYLIST_ENDMARKER - PLAYLIST_BEGINMARKER; + case PROP_TYPE_UNKNOWN: + return UNKNOWN_ENDMARKER - UNKNOWN_BEGINMARKER; + default: + return 0; + } + } + + inline size_t offset(PropertyType type) { + switch (type) { + case PROP_TYPE_SERVER: + return VIRTUALSERVER_BEGINMARKER; + case PROP_TYPE_CHANNEL: + return CHANNEL_BEGINMARKER; + case PROP_TYPE_CLIENT: + return CLIENT_BEGINMARKER; + case PROP_TYPE_CONNECTION: + return CONNECTION_BEGINMARKER; + case PROP_TYPE_GROUP: + return GROUP_BEGINMARKER; + case PROP_TYPE_INSTANCE: + return SERVERINSTANCE_BEGINMARKER; + case PROP_TYPE_PLAYLIST: + return PLAYLIST_BEGINMARKER; + case PROP_TYPE_UNKNOWN: + return UNKNOWN_BEGINMARKER; + default: + return 0; + } + } + + extern bool validateUnique(); + + extern bool validateInput(const std::string &, ValueType); + } + + + template + inline const std::shared_ptr &info(T property) { return impl::info(property); } + + template + inline const std::shared_ptr &info(const std::string& key) { return impl::info(key); } + + class PropertyDescription { + public: + static std::shared_ptr unknown; + + std::string name; + std::string default_value; + + ValueType type_value = property::ValueType::TYPE_UNKNOWN; + PropertyType type_property = PropertyType::PROP_TYPE_UNKNOWN; + + int property_index = 0; + flag_type flags = 0; + + PropertyDescription(int property_id, PropertyType property_type, const std::string &name, const std::string &default_value, property::ValueType type, flag_type flags) noexcept; + + template + PropertyDescription(T property, const std::string &name, const std::string &default_value, property::ValueType type, flag_type flags) noexcept : PropertyDescription((int) property, impl::type(), name, default_value, type, flags) {} + + inline bool operator==(const PropertyDescription& other) const { + return other.property_index == this->property_index && other.type_property == this->type_property; + } + + inline bool operator==(const std::shared_ptr& other) const { + return this->operator==(*other); + } + + template ::value, int>::type = 0> + inline bool operator==(const T& type) const { + return this->property_index == type && impl::type() == this->type_property; + } + + inline bool validate_input(const std::string& input) { + return impl::validateInput(input, this->type_value); + } + }; } class Properties; struct PropertyData { - spin_lock value_lock; - std::any casted_value; - std::string value; - std::shared_ptr description; + spin_lock value_lock; + std::any casted_value; + std::string value; + std::shared_ptr description; - bool flag_db_reference; - bool flag_modified; + bool flag_db_reference; + bool flag_modified; }; #ifdef WIN32 @@ -618,191 +618,191 @@ namespace ts { #pragma warning( disable : 4200 ) #endif struct PropertyBundle { - property::PropertyType type; - size_t length; - size_t offset; - PropertyData properties[0]; + property::PropertyType type; + size_t length; + size_t offset; + PropertyData properties[0]; }; #ifdef WIN32 #pragma warning( pop ) #endif - template - struct PropertyAccess { - inline static T get(PropertyData* data_ptr) { - std::lock_guard lock(data_ptr->value_lock); - if(data_ptr->casted_value.type() == typeid(T)) - return std::any_cast(data_ptr->casted_value); + template + struct PropertyAccess { + inline static T get(PropertyData* data_ptr) { + std::lock_guard lock(data_ptr->value_lock); + if(data_ptr->casted_value.type() == typeid(T)) + return std::any_cast(data_ptr->casted_value); - data_ptr->casted_value = ts::converter::from_string(data_ptr->value); - return std::any_cast(data_ptr->casted_value); - } - }; + data_ptr->casted_value = ts::converter::from_string(data_ptr->value); + return std::any_cast(data_ptr->casted_value); + } + }; - template <> - struct PropertyAccess { - inline static std::string get(PropertyData* data_ptr) { return data_ptr->value; } - }; + template <> + struct PropertyAccess { + inline static std::string get(PropertyData* data_ptr) { return data_ptr->value; } + }; - struct PropertyWrapper { - friend class Properties; - public: - bool operator==(const PropertyWrapper& other) { - if(this->data_ptr == other.data_ptr) - return true; + struct PropertyWrapper { + friend class Properties; + public: + bool operator==(const PropertyWrapper& other) { + if(this->data_ptr == other.data_ptr) + return true; - return this->data_ptr->value == other.data_ptr->value; - } + return this->data_ptr->value == other.data_ptr->value; + } - template - bool operator==(const T& other){ - return this->as() == other; - } - template - bool operator!=(const T& other){ - return !operator==(other); - } + template + bool operator==(const T& other){ + return this->as() == other; + } + template + bool operator!=(const T& other){ + return !operator==(other); + } - //Math operators - PropertyWrapper&operator++(){ return operator=(as() + 1); } - PropertyWrapper&operator++(int){ return operator=(as() + 1); } - PropertyWrapper&operator+=(uint16_t val){ return operator=(as() + val); } - PropertyWrapper&operator+=(int64_t val){ return operator=(as() + val); } - PropertyWrapper&operator+=(uint64_t val){ return operator=(as() + val); } + //Math operators + PropertyWrapper&operator++(){ return operator=(as() + 1); } + PropertyWrapper&operator++(int){ return operator=(as() + 1); } + PropertyWrapper&operator+=(uint16_t val){ return operator=(as() + val); } + PropertyWrapper&operator+=(int64_t val){ return operator=(as() + val); } + PropertyWrapper&operator+=(uint64_t val){ return operator=(as() + val); } - bool hasDbReference() const { return this->data_ptr->flag_db_reference; } - void setDbReference(bool flag){ this->data_ptr->flag_db_reference = flag; } + bool hasDbReference() const { return this->data_ptr->flag_db_reference; } + void setDbReference(bool flag){ this->data_ptr->flag_db_reference = flag; } - bool isModified() const { return this->data_ptr->flag_modified; } - void setModified(bool flag){ this->data_ptr->flag_modified = flag; } + bool isModified() const { return this->data_ptr->flag_modified; } + void setModified(bool flag){ this->data_ptr->flag_modified = flag; } - template - T as() const { - static_assert(ts::converter::supported, "as isn't supported for type"); + template + T as() const { + static_assert(ts::converter::supported, "as isn't supported for type"); - return PropertyAccess::get(this->data_ptr); - } + return PropertyAccess::get(this->data_ptr); + } - template - operator T(){ return this->as(); } + template + operator T(){ return this->as(); } - template - T as_save() const { - try { - std::lock_guard lock(this->data_ptr->value_lock); - if(this->data_ptr->casted_value.type() == typeid(T)) - return std::any_cast(this->data_ptr->casted_value); + template + T as_save() const { + try { + std::lock_guard lock(this->data_ptr->value_lock); + if(this->data_ptr->casted_value.type() == typeid(T)) + return std::any_cast(this->data_ptr->casted_value); - this->data_ptr->casted_value = ts::converter::from_string(this->data_ptr->value); - return std::any_cast(this->data_ptr->casted_value); - } catch(std::exception&) { - return 0; - } - } + this->data_ptr->casted_value = ts::converter::from_string(this->data_ptr->value); + return std::any_cast(this->data_ptr->casted_value); + } catch(std::exception&) { + return 0; + } + } - const property::PropertyDescription& type() const { return *this->data_ptr->description; } - std::string value() const { - std::lock_guard lock(this->data_ptr->value_lock); - return this->data_ptr->value; - } + const property::PropertyDescription& type() const { return *this->data_ptr->description; } + std::string value() const { + std::lock_guard lock(this->data_ptr->value_lock); + return this->data_ptr->value; + } - void value(const std::string &value, bool trigger_update = true){ - { - std::lock_guard lock(this->data_ptr->value_lock); - if(this->data_ptr->value == value) - return; - this->data_ptr->casted_value.reset(); - this->data_ptr->value = value; - } - if(trigger_update) - this->trigger_update(); - } + void value(const std::string &value, bool trigger_update = true){ + { + std::lock_guard lock(this->data_ptr->value_lock); + if(this->data_ptr->value == value) + return; + this->data_ptr->casted_value.reset(); + this->data_ptr->value = value; + } + if(trigger_update) + this->trigger_update(); + } - std::string default_value() const { - return this->type().default_value; - } + std::string default_value() const { + return this->type().default_value; + } - template - PropertyWrapper& operator=(const T& value) { - static_assert(ts::converter::supported, "type isn't supported for type"); + template + PropertyWrapper& operator=(const T& value) { + static_assert(ts::converter::supported, "type isn't supported for type"); - { - std::any any_value{value}; - auto value_string = ts::converter::to_string(any_value); + { + std::any any_value{value}; + auto value_string = ts::converter::to_string(any_value); - std::lock_guard lock(this->data_ptr->value_lock); - if(value_string == this->data_ptr->value) - return *this; - this->data_ptr->casted_value = any_value; - this->data_ptr->value = value_string; - } - this->trigger_update(); + std::lock_guard lock(this->data_ptr->value_lock); + if(value_string == this->data_ptr->value) + return *this; + this->data_ptr->casted_value = any_value; + this->data_ptr->value = value_string; + } + this->trigger_update(); - return *this; - } + return *this; + } - PropertyWrapper& operator=(const std::string& value) { - this->value(value); - return *this; - } - PropertyWrapper& operator=(const char* value) { - this->value(value); - return *this; - } + PropertyWrapper& operator=(const std::string& value) { + this->value(value); + return *this; + } + PropertyWrapper& operator=(const char* value) { + this->value(value); + return *this; + } - template - PropertyWrapper& operator=(char(value)[N]) { - this->value(value); - return *this; - } + template + PropertyWrapper& operator=(char(value)[N]) { + this->value(value); + return *this; + } - void trigger_update(); + void trigger_update(); - PropertyWrapper(Properties* /* handle */, PropertyData* /* ptr */, const std::shared_ptr& /* bundle */); + PropertyWrapper(Properties* /* handle */, PropertyData* /* ptr */, const std::shared_ptr& /* bundle */); - inline Properties* get_handle() { return this->handle; } - private: - Properties* handle = nullptr; - PropertyData* data_ptr = nullptr; - std::shared_ptr bundle_lock; - }; - typedef PropertyWrapper Property; - typedef std::function PropertyNotifyFn; + inline Properties* get_handle() { return this->handle; } + private: + Properties* handle = nullptr; + PropertyData* data_ptr = nullptr; + std::shared_ptr bundle_lock; + }; + typedef PropertyWrapper Property; + typedef std::function PropertyNotifyFn; class Properties { - friend struct PropertyWrapper; + friend struct PropertyWrapper; public: Properties(); ~Properties(); - Properties(const Properties&) = delete; - Properties(Properties&&) = delete; + Properties(const Properties&) = delete; + Properties(Properties&&) = delete; - std::vector list_properties(property::flag_type flagMask = (property::flag_type) ~0UL, property::flag_type negatedFlagMask = 0); - std::vector all_properties(); + std::vector list_properties(property::flag_type flagMask = (property::flag_type) ~0UL, property::flag_type negatedFlagMask = 0); + std::vector all_properties(); template bool register_property_type() { - constexpr auto type = property::impl::type(); + constexpr auto type = property::impl::type(); return this->register_property_type(type, property::impl::length(type), property::impl::offset(type)); } - template + template bool hasProperty(T type) { return this->has(property::impl::type(), type); } - template ::value, int>::type = 0> - PropertyWrapper operator[](T type) { - return this->find(property::impl::type(), type); - } + template ::value, int>::type = 0> + PropertyWrapper operator[](T type) { + return this->find(property::impl::type(), type); + } - PropertyWrapper operator[](const property::PropertyDescription& type) { - return this->find(type.type_property, type.property_index); - } + PropertyWrapper operator[](const property::PropertyDescription& type) { + return this->find(type.type_property, type.property_index); + } - PropertyWrapper operator[](const std::shared_ptr& type) { - return this->find(type->type_property, type->property_index); - } + PropertyWrapper operator[](const std::shared_ptr& type) { + return this->find(type->type_property, type->property_index); + } void registerNotifyHandler(const PropertyNotifyFn &fn){ this->notifyFunctions.push_back(fn); @@ -812,20 +812,20 @@ namespace ts { for(auto& prop : this->all_properties()) if(prop.isModified()) for(auto& elm : notifyFunctions) - elm(prop); + elm(prop); } void toggleSave(bool flag) { this->save = flag; } bool isSaveEnabled(){ return this->save; } - PropertyWrapper find(property::PropertyType type, int index); - bool has(property::PropertyType type, int index); + PropertyWrapper find(property::PropertyType type, int index); + bool has(property::PropertyType type, int index); - template ::value, int>::type = 0> - bool has(T type) { return this->has(property::impl::type(), type); } + template ::value, int>::type = 0> + bool has(T type) { return this->has(property::impl::type(), type); } private: - bool register_property_type(property::PropertyType /* type */, size_t /* length */, size_t /* offset */); + bool register_property_type(property::PropertyType /* type */, size_t /* length */, size_t /* offset */); bool save = true; std::vector> notifyFunctions{}; diff --git a/src/bbcode/bbcodes.cpp b/src/bbcode/bbcodes.cpp index e6a1fb0..56659fc 100644 --- a/src/bbcode/bbcodes.cpp +++ b/src/bbcode/bbcodes.cpp @@ -7,32 +7,32 @@ using namespace std; using namespace bbcode; bool bbcode::sloppy::has_tag(std::string message, std::deque tag) { - std::transform(message.begin(), message.end(), message.begin(), ::tolower); - for(auto& entry : tag) - std::transform(entry.begin(), entry.end(), entry.begin(), ::tolower); + std::transform(message.begin(), message.end(), message.begin(), ::tolower); + for(auto& entry : tag) + std::transform(entry.begin(), entry.end(), entry.begin(), ::tolower); - std::deque begins; - size_t index = 0, found, length = 0; - do { - found = string::npos; - for(auto it = tag.begin(); it != tag.end() && found == string::npos; it++) { - found = message.find(*it, index); - length = it->length(); - }; - if(found > 0 && found + length < message.length()) { - if(message[found + length] == ']' || (message[found + length] == '=' && message.find(']', found + length) != string::npos)) { - if(message[found - 1] == '/') { - auto found_tag = message.substr(found, length); - for(const auto& entry : begins) - if(entry == found_tag) return true; - } else if(message[found - 1] == '[' && (found < 2 || message[found - 2] != '\\')) - begins.push_back(message.substr(found, length)); - if(message[found + length] != ']') - found = message.find(']', found + length); - } - } - index = found + 1; - } while(index != 0); + std::deque begins; + size_t index = 0, found, length = 0; + do { + found = string::npos; + for(auto it = tag.begin(); it != tag.end() && found == string::npos; it++) { + found = message.find(*it, index); + length = it->length(); + }; + if(found > 0 && found + length < message.length()) { + if(message[found + length] == ']' || (message[found + length] == '=' && message.find(']', found + length) != string::npos)) { + if(message[found - 1] == '/') { + auto found_tag = message.substr(found, length); + for(const auto& entry : begins) + if(entry == found_tag) return true; + } else if(message[found - 1] == '[' && (found < 2 || message[found - 2] != '\\')) + begins.push_back(message.substr(found, length)); + if(message[found + length] != ']') + found = message.find(']', found + length); + } + } + index = found + 1; + } while(index != 0); - return false; + return false; } \ No newline at end of file diff --git a/src/bbcode/bbcodes.h b/src/bbcode/bbcodes.h index fec1832..b43c684 100644 --- a/src/bbcode/bbcodes.h +++ b/src/bbcode/bbcodes.h @@ -4,8 +4,8 @@ #include namespace bbcode::sloppy { - extern bool has_tag(std::string message, std::deque tag); + extern bool has_tag(std::string message, std::deque tag); - inline bool has_url(const std::string& message) { return has_tag(message, {"url"}); } - inline bool has_image(const std::string& message) { return has_tag(message, {"img"}); } - } \ No newline at end of file + inline bool has_url(const std::string& message) { return has_tag(message, {"url"}); } + inline bool has_image(const std::string& message) { return has_tag(message, {"img"}); } + } \ No newline at end of file diff --git a/src/channel/TreeView.cpp b/src/channel/TreeView.cpp index 1a26034..eb72137 100644 --- a/src/channel/TreeView.cpp +++ b/src/channel/TreeView.cpp @@ -7,44 +7,44 @@ using LinkedTreeEntry = ts::TreeView::LinkedTreeEntry; TreeView::TreeView() {} TreeView::~TreeView() { - std::deque> heads = {this->head}; - while(!heads.empty()) { - auto e = std::move(heads.front()); - heads.pop_front(); + std::deque> heads = {this->head}; + while(!heads.empty()) { + auto e = std::move(heads.front()); + heads.pop_front(); - while(e) { - if(e->child_head) - heads.push_back(e->child_head); + while(e) { + if(e->child_head) + heads.push_back(e->child_head); - //Release reference - if(e->previous) e->previous->next = nullptr; - e->previous = nullptr; - e->child_head = nullptr; - e = e->next; - } - } + //Release reference + if(e->previous) e->previous->next = nullptr; + e->previous = nullptr; + e->child_head = nullptr; + e = e->next; + } + } } std::shared_ptr TreeView::linked(const std::shared_ptr& entry) const { - if(!entry) return nullptr; + if(!entry) return nullptr; - std::deque> heads = {this->head}; - while(!heads.empty()) { - auto e = std::move(heads.front()); - heads.pop_front(); + std::deque> heads = {this->head}; + while(!heads.empty()) { + auto e = std::move(heads.front()); + heads.pop_front(); - while(e) { - if(e->entry->channelId() == entry->channelId()) - return e; - else { - if(e->child_head) - heads.push_back(e->child_head); - e = e->next; - } - } - } + while(e) { + if(e->entry->channelId() == entry->channelId()) + return e; + else { + if(e->child_head) + heads.push_back(e->child_head); + e = e->next; + } + } + } - return nullptr; + return nullptr; } std::deque> TreeView::query_deep(const std::shared_ptr& root, int deep) const { @@ -91,7 +91,7 @@ std::shared_ptr TreeView::find_entry(ts::ChannelId channelId) const { std::shared_ptr TreeView::find_linked_entry(ChannelId channelId, const std::shared_ptr& head, int deep) const { std::deque> heads; - heads.push_back(head ? head : this->head); + heads.push_back(head ? head : this->head); while(!heads.empty()) { @@ -102,18 +102,18 @@ std::shared_ptr TreeView::find_linked_entry(ChannelId channelId if(e->entry->channelId() == channelId) return e; if(e->child_head) { - if(deep-- == 0) { //Reached max deep. Dont go deeper - deep++; - } else { - if(e->next) heads.push_back(e->next); + if(deep-- == 0) { //Reached max deep. Dont go deeper + deep++; + } else { + if(e->next) heads.push_back(e->next); - e = e->child_head; - continue; - } + e = e->child_head; + continue; + } } e = e->next; } - deep++; + deep++; } return nullptr; @@ -124,12 +124,12 @@ std::deque> TreeView::entries(const std::shared_ptr> TreeView::entries_sub(const std::shared_ptr &root, int deep) const { - auto l_root = this->linked(root); - if(l_root && !l_root->child_head) return {root}; + auto l_root = this->linked(root); + if(l_root && !l_root->child_head) return {root}; - auto result = this->query_deep_entry(l_root ? l_root->child_head : l_root, deep); - result.push_back(root); - return result; + auto result = this->query_deep_entry(l_root ? l_root->child_head : l_root, deep); + result.push_back(root); + return result; } std::deque> TreeView::query_deep_entry(const shared_ptr& root, int deep) const { @@ -207,12 +207,12 @@ bool TreeView::move_entry(const std::shared_ptr &t_entry, const s /* cut the entry out */ this->cut_entry(entry); - entry->parent.reset(); + entry->parent.reset(); /* insert again */ if(!this->head) { this->head = entry; - entry->entry->setPreviousChannelId(0); + entry->entry->setPreviousChannelId(0); return true; } entry->parent = parent; @@ -245,7 +245,7 @@ bool TreeView::move_entry(const std::shared_ptr &t_entry, const s entry->next->previous = entry; entry->next->entry->setPreviousChannelId(entry->entry->channelId()); } - entry->entry->setPreviousChannelId(0); + entry->entry->setPreviousChannelId(0); } return true; diff --git a/src/channel/TreeView.h b/src/channel/TreeView.h index 59420f0..3320373 100644 --- a/src/channel/TreeView.h +++ b/src/channel/TreeView.h @@ -38,11 +38,11 @@ namespace ts { TreeView(); virtual ~TreeView(); - size_t entry_count() const; - std::deque> entries(const std::shared_ptr& /* head */ = nullptr, int /* deep */ = -1) const; - std::deque> entries_sub(const std::shared_ptr& /* parent */ = nullptr, int /* deep */ = -1) const; - std::shared_ptr find_entry(ChannelId /* channel id */) const; - std::shared_ptr find_linked_entry(ChannelId /* channel id */, const std::shared_ptr& /* head */ = nullptr, int deep = -1) const; + [[nodiscard]] size_t entry_count() const; + [[nodiscard]] std::deque> entries(const std::shared_ptr& /* head */ = nullptr, int /* deep */ = -1) const; + [[nodiscard]] std::deque> entries_sub(const std::shared_ptr& /* parent */ = nullptr, int /* deep */ = -1) const; + [[nodiscard]] std::shared_ptr find_entry(ChannelId /* channel id */) const; + [[nodiscard]] std::shared_ptr find_linked_entry(ChannelId /* channel id */, const std::shared_ptr& /* head */ = nullptr, int deep = -1) const; bool has_entry(const std::shared_ptr& /* entry */, const std::shared_ptr& /* head */ = nullptr, int deep = -1) const; diff --git a/src/converters/converter.h b/src/converters/converter.h index b85e461..434c860 100644 --- a/src/converters/converter.h +++ b/src/converters/converter.h @@ -3,83 +3,83 @@ #include namespace ts { - typedef long double long_double; + typedef long double long_double; - /* Converter stuff */ - template - struct converter { - static constexpr bool supported = false; + /* Converter stuff */ + template + struct converter { + static constexpr bool supported = false; - static constexpr std::string(*to_string)(const std::any&) = nullptr; - static constexpr T(*from_string)(const std::string&) = nullptr; - }; + static constexpr std::string(*to_string)(const std::any&) = nullptr; + static constexpr T(*from_string)(const std::string&) = nullptr; + }; - #define DECLARE_CONVERTER(type, decode, encode) \ - template <> \ - struct converter { \ - static constexpr bool supported = true; \ - \ - static constexpr std::string(*to_string)(const std::any&) = encode; \ - static constexpr type(*from_string)(const std::string&) = decode; \ - }; + #define DECLARE_CONVERTER(type, decode, encode) \ + template <> \ + struct converter { \ + static constexpr bool supported = true; \ + \ + static constexpr std::string(*to_string)(const std::any&) = encode; \ + static constexpr type(*from_string)(const std::string&) = decode; \ + }; - #define CONVERTER_METHOD_DECODE(type, name) type name(const std::string& str) - #define CONVERTER_METHOD_ENCODE(type, name) std::string name(const std::any& value) + #define CONVERTER_METHOD_DECODE(type, name) type name(const std::string& str) + #define CONVERTER_METHOD_ENCODE(type, name) std::string name(const std::any& value) - /* helper for primitive types */ - #define CONVERTER_PRIMITIVE(type) \ - namespace impl { \ - CONVERTER_METHOD_DECODE(type, converter_ ##type ##_decode); \ - CONVERTER_METHOD_ENCODE(type, converter_ ##type ##_encode); \ - } \ - DECLARE_CONVERTER(type, ::ts::impl::converter_ ##type ##_decode, ::ts::impl::converter_ ##type ##_encode); + /* helper for primitive types */ + #define CONVERTER_PRIMITIVE(type) \ + namespace impl { \ + CONVERTER_METHOD_DECODE(type, converter_ ##type ##_decode); \ + CONVERTER_METHOD_ENCODE(type, converter_ ##type ##_encode); \ + } \ + DECLARE_CONVERTER(type, ::ts::impl::converter_ ##type ##_decode, ::ts::impl::converter_ ##type ##_encode); - CONVERTER_PRIMITIVE(bool); - CONVERTER_PRIMITIVE(float); - CONVERTER_PRIMITIVE(double); - CONVERTER_PRIMITIVE(long_double); + CONVERTER_PRIMITIVE(bool); + CONVERTER_PRIMITIVE(float); + CONVERTER_PRIMITIVE(double); + CONVERTER_PRIMITIVE(long_double); - CONVERTER_PRIMITIVE(int8_t); - CONVERTER_PRIMITIVE(uint8_t); + CONVERTER_PRIMITIVE(int8_t); + CONVERTER_PRIMITIVE(uint8_t); - CONVERTER_PRIMITIVE(int16_t); - CONVERTER_PRIMITIVE(uint16_t); + CONVERTER_PRIMITIVE(int16_t); + CONVERTER_PRIMITIVE(uint16_t); - CONVERTER_PRIMITIVE(int32_t); - CONVERTER_PRIMITIVE(uint32_t); + CONVERTER_PRIMITIVE(int32_t); + CONVERTER_PRIMITIVE(uint32_t); - CONVERTER_PRIMITIVE(int64_t); - CONVERTER_PRIMITIVE(uint64_t); + CONVERTER_PRIMITIVE(int64_t); + CONVERTER_PRIMITIVE(uint64_t); - typedef std::string std__string; - typedef const char* const_char__; - CONVERTER_PRIMITIVE(std__string); - CONVERTER_PRIMITIVE(const_char__); + typedef std::string std__string; + typedef const char* const_char__; + CONVERTER_PRIMITIVE(std__string); + CONVERTER_PRIMITIVE(const_char__); - /* const expr char literal */ - template - struct converter { - using type = char[length]; - static constexpr bool supported = true; + /* const expr char literal */ + template + struct converter { + using type = char[length]; + static constexpr bool supported = true; - static constexpr std::string(*to_string)(const std::any&) = [](const std::any& value) { return std::string(std::any_cast(value), length - 1); }; - }; + static constexpr std::string(*to_string)(const std::any&) = [](const std::any& value) { return std::string(std::any_cast(value), length - 1); }; + }; - #undef CONVERTER_PRIMITIVE + #undef CONVERTER_PRIMITIVE } #define DEFINE_CONVERTER_ENUM(class, size_type) \ namespace ts { \ - template <> \ - struct converter { \ - static constexpr bool supported = true; \ - \ - static constexpr std::string(*to_string)(const std::any&) = [](const std::any& val) { \ - return std::to_string(std::any_cast(val)); \ - }; \ - static constexpr class(*from_string)(const std::string&) = [](const std::string& val) { \ - return ((class(*)(const std::string&)) ts::converter::from_string)(val); \ - }; \ - }; \ + template <> \ + struct converter { \ + static constexpr bool supported = true; \ + \ + static constexpr std::string(*to_string)(const std::any&) = [](const std::any& val) { \ + return std::to_string(std::any_cast(val)); \ + }; \ + static constexpr class(*from_string)(const std::string&) = [](const std::string& val) { \ + return ((class(*)(const std::string&)) ts::converter::from_string)(val); \ + }; \ + }; \ } /* DO NOT REMOVE ME (NL warning) */ \ No newline at end of file diff --git a/src/linked_helper.cpp b/src/linked_helper.cpp index 719bbba..8207093 100644 --- a/src/linked_helper.cpp +++ b/src/linked_helper.cpp @@ -7,127 +7,127 @@ using namespace std; using namespace linked; std::shared_ptr linked::build_chain(const std::deque> &entries, std::deque &log) { - //TODO filter only for one layer - auto find_entry = [&](uint64_t id) -> shared_ptr { - for(const auto& entry : entries) - if(entry->entry_id == id) - return entry; - return nullptr; - }; + //TODO filter only for one layer + auto find_entry = [&](uint64_t id) -> shared_ptr { + for(const auto& entry : entries) + if(entry->entry_id == id) + return entry; + return nullptr; + }; - deque> heads; - { - //first linking - for(const auto& entry : entries) { - auto previous = find_entry(entry->previous_id); - if(!previous && entry->previous_id > 0) { - log.emplace_back("missing " + to_string(entry->entry_id) + "'s previous entry (" + to_string(entry->previous_id) + "). Removing previous"); - entry->previous_id = 0; - entry->modified = true; - } + deque> heads; + { + //first linking + for(const auto& entry : entries) { + auto previous = find_entry(entry->previous_id); + if(!previous && entry->previous_id > 0) { + log.emplace_back("missing " + to_string(entry->entry_id) + "'s previous entry (" + to_string(entry->previous_id) + "). Removing previous"); + entry->previous_id = 0; + entry->modified = true; + } - if(previous) { - /* validate previous stuff */ - if((previous->next && previous->next != entry)) { - log.emplace_back(to_string(entry->entry_id) + "'s previous node has already someone linked (" + to_string(previous->next->entry_id) + "). Removing previous"); - entry->previous_id = 0; - entry->modified = true; - previous = nullptr; - } else if(previous == entry) { - log.emplace_back(to_string(entry->entry_id) + "'s previous node references to himself. Removing previous"); - entry->previous_id = 0; - entry->modified = true; - previous = nullptr; - } - } - if(previous) { - previous->next = entry; - entry->previous = previous; - } else { - heads.push_back(entry); - } - } - } + if(previous) { + /* validate previous stuff */ + if((previous->next && previous->next != entry)) { + log.emplace_back(to_string(entry->entry_id) + "'s previous node has already someone linked (" + to_string(previous->next->entry_id) + "). Removing previous"); + entry->previous_id = 0; + entry->modified = true; + previous = nullptr; + } else if(previous == entry) { + log.emplace_back(to_string(entry->entry_id) + "'s previous node references to himself. Removing previous"); + entry->previous_id = 0; + entry->modified = true; + previous = nullptr; + } + } + if(previous) { + previous->next = entry; + entry->previous = previous; + } else { + heads.push_back(entry); + } + } + } - { - /* - * Now test for circles (the heads could not contain a circle because they have one open end) - * But we've may nodes which are not within the heads - */ + { + /* + * Now test for circles (the heads could not contain a circle because they have one open end) + * But we've may nodes which are not within the heads + */ - unordered_map used_nodes; - deque> unused_nodes; + unordered_map used_nodes; + deque> unused_nodes; - for(auto head : heads) { - while(head) { - auto& value = used_nodes[&*head]; - if(value) { - //Node has been already used - log.emplace_back(to_string(head->entry_id) + "'s has already been used, but is linked in another chain! We could not recover from that"); - return nullptr; - } else - value = 1; + for(auto head : heads) { + while(head) { + auto& value = used_nodes[&*head]; + if(value) { + //Node has been already used + log.emplace_back(to_string(head->entry_id) + "'s has already been used, but is linked in another chain! We could not recover from that"); + return nullptr; + } else + value = 1; - head = head->next; - } - } + head = head->next; + } + } - for(const auto& node : entries) { - if(!used_nodes[&*node]) - unused_nodes.push_back(node); - } + for(const auto& node : entries) { + if(!used_nodes[&*node]) + unused_nodes.push_back(node); + } - while(!unused_nodes.empty()) { - auto head = std::move(unused_nodes.front()); - unused_nodes.pop_front(); + while(!unused_nodes.empty()) { + auto head = std::move(unused_nodes.front()); + unused_nodes.pop_front(); - log.emplace_back("Found circle. Cutting circle between " + to_string(head->previous->entry_id) + " and " + to_string(head->entry_id)); - if(head->previous->next == head) - head->previous->next = nullptr; + log.emplace_back("Found circle. Cutting circle between " + to_string(head->previous->entry_id) + " and " + to_string(head->entry_id)); + if(head->previous->next == head) + head->previous->next = nullptr; - head->previous = nullptr; - head->previous_id = 0; - head->modified = true; + head->previous = nullptr; + head->previous_id = 0; + head->modified = true; - heads.push_back(head); - while(head->next) { - auto it = find(unused_nodes.begin(), unused_nodes.end(), head->next); - if(it != unused_nodes.end()) { - unused_nodes.erase(it); - } else { - log.emplace_back(to_string(head->entry_id) + "'s has already been used, but is linked in another chain! We could not recover from that"); - return nullptr; - } - } - } + heads.push_back(head); + while(head->next) { + auto it = find(unused_nodes.begin(), unused_nodes.end(), head->next); + if(it != unused_nodes.end()) { + unused_nodes.erase(it); + } else { + log.emplace_back(to_string(head->entry_id) + "'s has already been used, but is linked in another chain! We could not recover from that"); + return nullptr; + } + } + } - if(heads.empty()) { - if(!entries.empty()) - log.emplace_back("failed to detect heads! We could not recover from that"); - return nullptr; - } + if(heads.empty()) { + if(!entries.empty()) + log.emplace_back("failed to detect heads! We could not recover from that"); + return nullptr; + } - auto head = heads.front(); - heads.pop_front(); + auto head = heads.front(); + heads.pop_front(); - auto tail = head; - while(tail->next) tail = tail->next; + auto tail = head; + while(tail->next) tail = tail->next; - while(!heads.empty()) { + while(!heads.empty()) { - auto local_head = heads.front(); - heads.pop_front(); + auto local_head = heads.front(); + heads.pop_front(); - log.emplace_back("Appending open begin (" + to_string(local_head->entry_id) + ") to current tail (" + to_string(tail->entry_id) + ")"); - local_head->previous = tail; - local_head->previous_id = tail->entry_id; - local_head->modified = true; + log.emplace_back("Appending open begin (" + to_string(local_head->entry_id) + ") to current tail (" + to_string(tail->entry_id) + ")"); + local_head->previous = tail; + local_head->previous_id = tail->entry_id; + local_head->modified = true; - tail->next = local_head; + tail->next = local_head; - while(tail->next) tail = tail->next; /* walk to the tail again */ - } + while(tail->next) tail = tail->next; /* walk to the tail again */ + } - return head; - } + return head; + } } \ No newline at end of file diff --git a/src/linked_helper.h b/src/linked_helper.h index bfeb2d3..ae9f7b1 100644 --- a/src/linked_helper.h +++ b/src/linked_helper.h @@ -4,27 +4,27 @@ #include namespace linked { - struct entry { - std::shared_ptr previous; - std::shared_ptr next; - std::shared_ptr child_head; + struct entry { + std::shared_ptr previous; + std::shared_ptr next; + std::shared_ptr child_head; - uint64_t parent_id; - uint64_t entry_id; - uint64_t previous_id; + uint64_t parent_id; + uint64_t entry_id; + uint64_t previous_id; - bool fully_linked = false; - bool modified = false; - }; + bool fully_linked = false; + bool modified = false; + }; - inline std::shared_ptr create_entry(uint64_t parent_id, uint64_t entry_id, uint64_t previous_id) { - auto result = std::make_shared(); - result->parent_id = parent_id; - result->entry_id = entry_id; - result->previous_id = previous_id; + inline std::shared_ptr create_entry(uint64_t parent_id, uint64_t entry_id, uint64_t previous_id) { + auto result = std::make_shared(); + result->parent_id = parent_id; + result->entry_id = entry_id; + result->previous_id = previous_id; - return result; - } + return result; + } - extern std::shared_ptr build_chain(const std::deque>& /* entried */, std::deque& /* error log */); + extern std::shared_ptr build_chain(const std::deque>& /* entried */, std::deque& /* error log */); } \ No newline at end of file diff --git a/src/log/LogSinks.cpp b/src/log/LogSinks.cpp index b13ed0e..1b080f7 100644 --- a/src/log/LogSinks.cpp +++ b/src/log/LogSinks.cpp @@ -10,122 +10,122 @@ using namespace std; using namespace spdlog; namespace logger { - void TerminalSink::sink_it_(const spdlog::details::log_msg &msg) { - memory_buf_t formatted; - this->formatter_->format(msg, formatted); + void TerminalSink::sink_it_(const spdlog::details::log_msg &msg) { + memory_buf_t formatted; + this->formatter_->format(msg, formatted); - std::string_view message{formatted.data(), formatted.size()}; + std::string_view message{formatted.data(), formatted.size()}; - #ifdef HAVE_CXX_TERMINAL - if (terminal::active()) { - //Split the string at new lines - size_t index{0}, found{0}; - do { - found = message.find('\n', index); - const auto length = (found == -1 ? message.length() : found) - index; - const auto line = message.substr(index, length); + #ifdef HAVE_CXX_TERMINAL + if (terminal::active()) { + //Split the string at new lines + size_t index{0}, found{0}; + do { + found = message.find('\n', index); + const auto length = (found == -1 ? message.length() : found) - index; + const auto line = message.substr(index, length); - index = found; - if(length == 0) continue; + index = found; + if(length == 0) continue; - terminal::instance()->writeMessage(std::string{line}); - } while(++index); - } else - #endif - cout << message; - } + terminal::instance()->writeMessage(std::string{line}); + } while(++index); + } else + #endif + cout << message; + } - void TerminalSink::flush_() {} + void TerminalSink::flush_() {} - inline void append_time(const log_clock::time_point& point, memory_buf_t& dest) { - std::time_t time = log_clock::to_time_t(point); - std::tm timetm = *std::localtime(&time); + inline void append_time(const log_clock::time_point& point, memory_buf_t& dest) { + std::time_t time = log_clock::to_time_t(point); + std::tm timetm = *std::localtime(&time); - static constexpr auto max_length = 9; - dest.reserve(dest.size() + max_length); + static constexpr auto max_length = 9; + dest.reserve(dest.size() + max_length); - auto length = strftime(dest.end(), max_length, "%H:%M:%S", &timetm); - if(length < 0) - length = 0; + auto length = strftime(dest.end(), max_length, "%H:%M:%S", &timetm); + if(length < 0) + length = 0; - dest.resize(dest.size() + length); - } + dest.resize(dest.size() + length); + } #ifdef HAVE_CXX_TERMINAL - static constexpr std::array level_mapping_colored{ - " [" ANSI_LIGHT_BLUE "TRACE" ANSI_RESET "] ", - " [" ANSI_LIGHT_BLUE "DEBUG" ANSI_RESET "] ", - " [" ANSI_YELLOW "INFO " ANSI_RESET "] ", - " [" ANSI_BROWN "WARNING " ANSI_RESET "] ", - " [" ANSI_RED "ERROR" ANSI_RESET "] ", - " [" ANSI_RED ANSI_BOLD ANSI_REVERSE "CRITICAL" ANSI_RESET "] ", - " [" ANSI_GRAY "OFF " ANSI_RESET "] " - }; + static constexpr std::array level_mapping_colored{ + " [" ANSI_LIGHT_BLUE "TRACE" ANSI_RESET "] ", + " [" ANSI_LIGHT_BLUE "DEBUG" ANSI_RESET "] ", + " [" ANSI_YELLOW "INFO " ANSI_RESET "] ", + " [" ANSI_BROWN "WARNING " ANSI_RESET "] ", + " [" ANSI_RED "ERROR" ANSI_RESET "] ", + " [" ANSI_RED ANSI_BOLD ANSI_REVERSE "CRITICAL" ANSI_RESET "] ", + " [" ANSI_GRAY "OFF " ANSI_RESET "] " + }; #endif - static constexpr std::array level_mapping{ - " [TRACE] ", - " [DEBUG] ", - " [INFO ] ", - " [WARNING ] ", - " [ERROR] ", - " [CRITICAL] ", - " [OFF ] " - }; + static constexpr std::array level_mapping{ + " [TRACE] ", + " [DEBUG] ", + " [INFO ] ", + " [WARNING ] ", + " [ERROR] ", + " [CRITICAL] ", + " [OFF ] " + }; - void LogFormatter::format(const details::log_msg &msg, memory_buf_t &dest) { - const auto append = [&](const std::string_view& message) { dest.append(message.data(), message.data() + message.length()); }; + void LogFormatter::format(const details::log_msg &msg, memory_buf_t &dest) { + const auto append = [&](const std::string_view& message) { dest.append(message.data(), message.data() + message.length()); }; - dest.clear(); - auto prefix_begin = dest.end(); - //Time - { - dest.push_back('['); - append_time(msg.time, dest); - dest.push_back(']'); - } + dest.clear(); + auto prefix_begin = dest.end(); + //Time + { + dest.push_back('['); + append_time(msg.time, dest); + dest.push_back(']'); + } - //Level - { + //Level + { #ifdef HAVE_CXX_TERMINAL - const auto& mapping = this->_colored ? level_mapping_colored : level_mapping; + const auto& mapping = this->_colored ? level_mapping_colored : level_mapping; #else const auto& mapping = level_mapping; #endif - size_t level = msg.level.value; - if(level >= mapping.size()) - level = mapping.size() - 1; + size_t level = msg.level.value; + if(level >= mapping.size()) + level = mapping.size() - 1; - append(mapping[level]); - } - auto prefix_end = dest.end(); + append(mapping[level]); + } + auto prefix_end = dest.end(); - //Append the prefix to every line - std::string_view payload{msg.payload.data(), msg.payload.size()}; - size_t index{0}, found{0}; - while(true) { - found = payload.find(spdlog::details::os::default_eol, index); - auto line = payload.substr(index, (found == -1 ? payload.length() : found) - index); + //Append the prefix to every line + std::string_view payload{msg.payload.data(), msg.payload.size()}; + size_t index{0}, found{0}; + while(true) { + found = payload.find(spdlog::details::os::default_eol, index); + auto line = payload.substr(index, (found == -1 ? payload.length() : found) - index); #ifdef HAVE_CXX_TERMINAL - auto colored = this->_colored ? terminal::parseCharacterCodes(std::string{line}) : terminal::stripCharacterCodes(std::string{line}); + auto colored = this->_colored ? terminal::parseCharacterCodes(std::string{line}) : terminal::stripCharacterCodes(std::string{line}); #else - auto colored = line; + auto colored = line; #endif - dest.append(colored.data(), colored.data() + colored.size()); + dest.append(colored.data(), colored.data() + colored.size()); - index = found; + index = found; - append(spdlog::details::os::default_eol); - if(++index) - dest.append(prefix_begin, prefix_end); - else - break; - } - } + append(spdlog::details::os::default_eol); + if(++index) + dest.append(prefix_begin, prefix_end); + else + break; + } + } - [[nodiscard]] std::unique_ptr LogFormatter::clone() const { - return std::make_unique(this->_colored); - } + [[nodiscard]] std::unique_ptr LogFormatter::clone() const { + return std::make_unique(this->_colored); + } } \ No newline at end of file diff --git a/src/log/LogSinks.h b/src/log/LogSinks.h index 8474499..b894265 100644 --- a/src/log/LogSinks.h +++ b/src/log/LogSinks.h @@ -4,34 +4,34 @@ #include namespace logger { - class ColorCodeFormatter : public spdlog::formatter { - public: - void format(const spdlog::details::log_msg &msg, spdlog::memory_buf_t &dest) override { - dest.append(msg.payload.begin(), msg.payload.end()); - } - - [[nodiscard]] std::unique_ptr clone() const override { - return std::unique_ptr(); - } - }; - - //TODO: Mutex really needed here? - class TerminalSink : public spdlog::sinks::base_sink { + class ColorCodeFormatter : public spdlog::formatter { public: - void sink_it_(const spdlog::details::log_msg &msg) override; - void flush_() override; + void format(const spdlog::details::log_msg &msg, spdlog::memory_buf_t &dest) override { + dest.append(msg.payload.begin(), msg.payload.end()); + } + + [[nodiscard]] std::unique_ptr clone() const override { + return std::unique_ptr(); + } }; - class LogFormatter : public spdlog::formatter { - public: - explicit LogFormatter(bool colored) : _colored{colored} {} + //TODO: Mutex really needed here? + class TerminalSink : public spdlog::sinks::base_sink { + public: + void sink_it_(const spdlog::details::log_msg &msg) override; + void flush_() override; + }; - void format(const spdlog::details::log_msg &msg, spdlog::memory_buf_t &dest) override; - [[nodiscard]] std::unique_ptr clone() const override; + class LogFormatter : public spdlog::formatter { + public: + explicit LogFormatter(bool colored) : _colored{colored} {} - inline bool colored() const { return this->_colored; } - inline void colored(bool flag) { this->_colored = flag; } - private: - bool _colored{true}; - }; + void format(const spdlog::details::log_msg &msg, spdlog::memory_buf_t &dest) override; + [[nodiscard]] std::unique_ptr clone() const override; + + inline bool colored() const { return this->_colored; } + inline void colored(bool flag) { this->_colored = flag; } + private: + bool _colored{true}; + }; } diff --git a/src/log/LogUtils.cpp b/src/log/LogUtils.cpp index 5a78bc8..d392179 100644 --- a/src/log/LogUtils.cpp +++ b/src/log/LogUtils.cpp @@ -36,66 +36,66 @@ namespace logger { spdlog::level::level_enum min_level{spdlog::level::trace}; - void updater_logger_levels(const std::shared_ptr& logger) { - for(const auto& sink : logger->sinks()) - if(dynamic_pointer_cast(sink)) { - sink->set_level(::logger::currentConfig()->terminalLevel); - } else if(dynamic_pointer_cast(sink)) { - sink->set_level(::logger::currentConfig()->logfileLevel); - } else if(dynamic_pointer_cast(sink)) { - sink->set_level(::logger::currentConfig()->logfileLevel); - } else { - sink->set_level(min_level); - } - logger->set_level(min_level); - } + void updater_logger_levels(const std::shared_ptr& logger) { + for(const auto& sink : logger->sinks()) + if(dynamic_pointer_cast(sink)) { + sink->set_level(::logger::currentConfig()->terminalLevel); + } else if(dynamic_pointer_cast(sink)) { + sink->set_level(::logger::currentConfig()->logfileLevel); + } else if(dynamic_pointer_cast(sink)) { + sink->set_level(::logger::currentConfig()->logfileLevel); + } else { + sink->set_level(min_level); + } + logger->set_level(min_level); + } - std::string generate_log_file(size_t group) { - return strvar::transform(logConfig->logPath, - strvar::StringValue{"group", group != -1 ? to_string(group) : "general"}, - strvar::FunctionValue("time", (strvar::FunctionValue::FValueFNEasy) [](std::deque value) -> std::string { - auto pattern = !value.empty() ? value[0] : "%Y-%m-%d_%H:%M:%S"; + std::string generate_log_file(size_t group) { + return strvar::transform(logConfig->logPath, + strvar::StringValue{"group", group != -1 ? to_string(group) : "general"}, + strvar::FunctionValue("time", (strvar::FunctionValue::FValueFNEasy) [](std::deque value) -> std::string { + auto pattern = !value.empty() ? value[0] : "%Y-%m-%d_%H:%M:%S"; - auto secs = duration_cast(logConfig->timestamp.time_since_epoch()).count(); - tm* tm_info; + auto secs = duration_cast(logConfig->timestamp.time_since_epoch()).count(); + tm* tm_info; #ifdef WIN32 - tm _tm_info{}; + tm _tm_info{}; localtime_s(&_tm_info, &secs); tm_info = &_tm_info; #else - tm_info = localtime((time_t*) &secs); + tm_info = localtime((time_t*) &secs); #endif - char timeBuffer[1024]; - if(strftime(timeBuffer, 1024, pattern.c_str(), tm_info) == 0) { - return string("string is longer than the buffer"); - } + char timeBuffer[1024]; + if(strftime(timeBuffer, 1024, pattern.c_str(), tm_info) == 0) { + return string("string is longer than the buffer"); + } - return string(timeBuffer); - }) - ); - } + return string(timeBuffer); + }) + ); + } - std::mutex default_lock{}; - bool default_setup{false}; + std::mutex default_lock{}; + bool default_setup{false}; - std::shared_ptr default_logger() { - lock_guard lock{default_lock}; - if(!default_setup) { - default_setup = true; + std::shared_ptr default_logger() { + lock_guard lock{default_lock}; + if(!default_setup) { + default_setup = true; - spdlog::default_logger()->sinks().clear(); - auto terminal_sink = make_shared(); - terminal_sink->set_level(spdlog::level::trace); - spdlog::default_logger()->sinks().push_back(terminal_sink); + spdlog::default_logger()->sinks().clear(); + auto terminal_sink = make_shared(); + terminal_sink->set_level(spdlog::level::trace); + spdlog::default_logger()->sinks().push_back(terminal_sink); - spdlog::default_logger()->set_formatter(std::make_unique(true)); - } - return spdlog::default_logger(); - } + spdlog::default_logger()->set_formatter(std::make_unique(true)); + } + return spdlog::default_logger(); + } shared_ptr logger(int serverId) { if(!::logger::currentConfig()) - return default_logger(); + return default_logger(); size_t group = 0; if(::logger::currentConfig()->vs_group_size > 0 && serverId > 0) @@ -107,45 +107,45 @@ namespace logger { if(loggers.count(group) > 0) return loggers[group]; //Create a new logger if(group != 0 && group != -1) - logger(0)->debug("Creating new grouped logger for group {}", group); + logger(0)->debug("Creating new grouped logger for group {}", group); - vector sinks; - string path; - if(logConfig->logfileLevel != spdlog::level::off) { - path = generate_log_file(group); + vector sinks; + string path; + if(logConfig->logfileLevel != spdlog::level::off) { + path = generate_log_file(group); - auto logFile = fs::u8path(path); - if(!logFile.parent_path().empty()) - fs::create_directories(logFile.parent_path()); + auto logFile = fs::u8path(path); + if(!logFile.parent_path().empty()) + fs::create_directories(logFile.parent_path()); - try { - auto sink = make_shared(logFile.string(), 1024 * 1024 * 50, 12); - sink->set_formatter(std::make_unique(::logger::currentConfig()->file_colored)); - sinks.push_back(sink); - } catch(std::exception& ex) { - if(group != 0 && group != -1) - logger(0)->critical("Failed to create file for new log group: {}", ex.what()); - else + try { + auto sink = make_shared(logFile.string(), 1024 * 1024 * 50, 12); + sink->set_formatter(std::make_unique(::logger::currentConfig()->file_colored)); + sinks.push_back(sink); + } catch(std::exception& ex) { + if(group != 0 && group != -1) + logger(0)->critical("Failed to create file for new log group: {}", ex.what()); + else #ifdef HAVE_CXX_TERMINAL - terminal::instance()->writeMessage("§4[CRITICAL] §eFailed to create main log file: " + string{ex.what()}, false); + terminal::instance()->writeMessage("§4[CRITICAL] §eFailed to create main log file: " + string{ex.what()}, false); #else - std::cout << "[CRITICAL] Failed to create main log file: " << ex.what() << "\n"; + std::cout << "[CRITICAL] Failed to create main log file: " << ex.what() << "\n"; #endif - } - } else { - path = "/dev/null (" + to_string(group) + ")"; - } + } + } else { + path = "/dev/null (" + to_string(group) + ")"; + } sinks.push_back(terminalSink); - if(!logging_threads) - logging_threads = std::make_shared(8192, 1); //Only one thread possible here, else elements get reordered + if(!logging_threads) + logging_threads = std::make_shared(8192, 1); //Only one thread possible here, else elements get reordered #ifdef ASYNC_LOG auto logger = std::make_shared("Logger (" + path + ")", sinks.begin(), sinks.end(), logging_threads, async_overflow_policy::block); #else //FIXME! auto logger = create("Logger (" + path + ")", sinks.begin(), sinks.end()); #endif - updater_logger_levels(logger); + updater_logger_levels(logger); loggers[group] = logger; } @@ -160,72 +160,72 @@ namespace logger { logConfig = config; config->timestamp = system_clock::now(); - terminalSink = make_shared(); - terminalSink->set_level(::logger::currentConfig()->terminalLevel); - terminalSink->set_formatter(std::make_unique(true)); - min_level = ::min(::logger::currentConfig()->logfileLevel, ::logger::currentConfig()->terminalLevel); + terminalSink = make_shared(); + terminalSink->set_level(::logger::currentConfig()->terminalLevel); + terminalSink->set_formatter(std::make_unique(true)); + min_level = ::min(::logger::currentConfig()->logfileLevel, ::logger::currentConfig()->terminalLevel); logger(0)->debug("Log successfully started!"); } - bool should_log(spdlog::level::level_enum level) { - return level >= min_level; - } + bool should_log(spdlog::level::level_enum level) { + return level >= min_level; + } - void log(spdlog::level::forceable level, int server_id, const std::string_view& buffer) { - auto logger = ::logger::logger(server_id); + void log(spdlog::level::forceable level, int server_id, const std::string_view& buffer) { + auto logger = ::logger::logger(server_id); - auto message_format = "§8{0:>5} | §r{1}"; - if(server_id <= 0) { - switch (server_id) { - case LOG_INSTANCE: - message_format = "§8GLOBL | §r{1}"; - break; - case LOG_QUERY: - message_format = "§8QUERY | §r{1}"; - break; - case LOG_FT: - message_format = "§8 FILE | §r{1}"; - break; - case LOG_GENERAL: - message_format = "§8 GEN | §r{1}"; - break; - case LOG_LICENSE_CONTROLL: - message_format = "§8 CONTR | §r{1}"; - break; - case LOG_LICENSE_WEB: - message_format = "§8 WEBST | §r{1}"; - break; + auto message_format = "§8{0:>5} | §r{1}"; + if(server_id <= 0) { + switch (server_id) { + case LOG_INSTANCE: + message_format = "§8GLOBL | §r{1}"; + break; + case LOG_QUERY: + message_format = "§8QUERY | §r{1}"; + break; + case LOG_FT: + message_format = "§8 FILE | §r{1}"; + break; + case LOG_GENERAL: + message_format = "§8 GEN | §r{1}"; + break; + case LOG_LICENSE_CONTROLL: + message_format = "§8 CONTR | §r{1}"; + break; + case LOG_LICENSE_WEB: + message_format = "§8 WEBST | §r{1}"; + break; - default: - break; - } - } + default: + break; + } + } - try { - logger->log(level, message_format, server_id, buffer); - } catch (const std::exception &ex) { - //TODO better? - std::cerr << "An exception has raised while logging a message (" << ex.what() << "): " << buffer << "\n"; - } catch(...) { - std::cerr << "An unknown exception has raised while logging a message: " << buffer << "\n"; - throw; - } - } + try { + logger->log(level, message_format, server_id, buffer); + } catch (const std::exception &ex) { + //TODO better? + std::cerr << "An exception has raised while logging a message (" << ex.what() << "): " << buffer << "\n"; + } catch(...) { + std::cerr << "An unknown exception has raised while logging a message: " << buffer << "\n"; + throw; + } + } void updateLogLevels() { lock_guard lock(loggerLock); - min_level = ::min(::logger::currentConfig()->logfileLevel, ::logger::currentConfig()->terminalLevel); + min_level = ::min(::logger::currentConfig()->logfileLevel, ::logger::currentConfig()->terminalLevel); for(const auto& logger : loggers) { - updater_logger_levels(logger.second); + updater_logger_levels(logger.second); } } void flush() { unique_lock lock(loggerLock); auto _loggers = loggers; - lock.unlock(); + lock.unlock(); for(const auto& loggerEntry : _loggers) { loggerEntry.second->flush(); @@ -241,8 +241,8 @@ namespace logger { loggers.clear(); spdlog::drop_all(); - logConfig = nullptr; - terminalSink = nullptr; + logConfig = nullptr; + terminalSink = nullptr; } } @@ -269,10 +269,10 @@ void hexDump(void *addr, int len, int pad,int columnLength, void (*print)(string if ((i % pad) == 0) { // Just don't print ASCII for the zeroth line. if (i != 0) { - line << buff; - print(line.str()); - line = stringstream{}; - line << hex; + line << buff; + print(line.str()); + line = stringstream{}; + line << hex; }; // Output the offset. @@ -302,8 +302,8 @@ void hexDump(void *addr, int len, int pad,int columnLength, void (*print)(string line << buff; delete[] buff; - print(line.str()); - line = stringstream{}; + print(line.str()); + line = stringstream{}; line << "Length: " << dec << len << " Addr: " << addr; - print(line.str()); + print(line.str()); } diff --git a/src/log/LogUtils.h b/src/log/LogUtils.h index 48ca3c7..ee3f7e4 100644 --- a/src/log/LogUtils.h +++ b/src/log/LogUtils.h @@ -2,11 +2,11 @@ #define SPDLOG_EOL "\n" #ifdef SPDLOG_FINAL - #undef SPDLOG_FINAL + #undef SPDLOG_FINAL #endif #define SPDLOG_FINAL #ifdef byte - #undef byte + #undef byte #endif #include @@ -24,43 +24,43 @@ #undef log #endif namespace logger { - struct LoggerConfig { - spdlog::level::level_enum logfileLevel = spdlog::level::info; - spdlog::level::level_enum terminalLevel = spdlog::level::info; - bool file_colored; - std::string logPath = "log_${time}.log"; - size_t vs_group_size = 1; - std::chrono::system_clock::time_point timestamp; - }; + struct LoggerConfig { + spdlog::level::level_enum logfileLevel = spdlog::level::info; + spdlog::level::level_enum terminalLevel = spdlog::level::info; + bool file_colored; + std::string logPath = "log_${time}.log"; + size_t vs_group_size = 1; + std::chrono::system_clock::time_point timestamp; + }; - extern std::shared_ptr logger(int); - extern void setup(const std::shared_ptr&); - extern const std::shared_ptr& currentConfig(); - extern void uninstall(); + extern std::shared_ptr logger(int); + extern void setup(const std::shared_ptr&); + extern const std::shared_ptr& currentConfig(); + extern void uninstall(); - extern bool should_log(spdlog::level::level_enum /* level */); //TODO: inline? - extern void log(spdlog::level::forceable /* level */, int /* server id */, const std::string_view& /* buffer */); + extern bool should_log(spdlog::level::level_enum /* level */); //TODO: inline? + extern void log(spdlog::level::forceable /* level */, int /* server id */, const std::string_view& /* buffer */); - extern void updateLogLevels(); - extern void flush(); + extern void updateLogLevels(); + extern void flush(); - namespace impl { - template - inline void do_log(bool forced, int serverId, const std::string& message, const Args&... args) { - if(!forced && !::logger::should_log(level)) return; - spdlog::memory_buf_t buffer{}; + namespace impl { + template + inline void do_log(bool forced, int serverId, const std::string& message, const Args&... args) { + if(!forced && !::logger::should_log(level)) return; + spdlog::memory_buf_t buffer{}; - auto _logger = ::logger::logger(serverId); - std::string fmt_message; - try { - fmt_message = fmt::format(message, args...); - } catch (const std::exception &ex) { - fmt_message = "failed to format message '" + std::string{message} + "': " + ex.what(); - } + auto _logger = ::logger::logger(serverId); + std::string fmt_message; + try { + fmt_message = fmt::format(message, args...); + } catch (const std::exception &ex) { + fmt_message = "failed to format message '" + std::string{message} + "': " + ex.what(); + } - ::logger::log(spdlog::level::forceable{level, forced}, serverId, fmt_message); - } - } + ::logger::log(spdlog::level::forceable{level, forced}, serverId, fmt_message); + } + } } #define LOG_LICENSE_CONTROLL (-0x10) @@ -74,7 +74,7 @@ namespace logger { #define DEFINE_LOG_IMPL(name, level, _default_prefix) \ template \ inline void name ##Fmt(bool forced, int serverId, const std::string& message, const Args&... args) { \ - ::logger::impl::do_log(forced, serverId, message, args...); \ + ::logger::impl::do_log(forced, serverId, message, args...); \ } DEFINE_LOG_IMPL(logMessage, spdlog::level::info, "INFO") diff --git a/src/log/translation.h b/src/log/translation.h index c6e00c6..4f85c43 100644 --- a/src/log/translation.h +++ b/src/log/translation.h @@ -1,13 +1,13 @@ #pragma once namespace tr { - enum Messages { - kick_invalid_badges, - kick_invalid_packet, - kick_invalid_command, + enum Messages { + kick_invalid_badges, + kick_invalid_packet, + kick_invalid_command, - crash_instance, - shutdown_instance, - shutdown_server, - }; + crash_instance, + shutdown_instance, + shutdown_server, + }; } \ No newline at end of file diff --git a/src/misc/advanced_mutex.h b/src/misc/advanced_mutex.h index 665f15f..40a1c68 100644 --- a/src/misc/advanced_mutex.h +++ b/src/misc/advanced_mutex.h @@ -8,200 +8,200 @@ #include namespace std { - template - struct lock_guarded { - Lock l; - T *t; + template + struct lock_guarded { + Lock l; + T *t; - T *operator->() &&{ return t; } + T *operator->() &&{ return t; } - template - auto operator[](Arg &&arg) && -> decltype(std::declval()[std::declval()]) { - return (*t)[std::forward(arg)]; - } + template + auto operator[](Arg &&arg) && -> decltype(std::declval()[std::declval()]) { + return (*t)[std::forward(arg)]; + } - T &operator*() &&{ return *t; } - }; + T &operator*() &&{ return *t; } + }; - template - struct lock_guarded_shared { - Lock l; - std::shared_ptr t; + template + struct lock_guarded_shared { + Lock l; + std::shared_ptr t; - T *operator->() &&{ return t.operator->(); } + T *operator->() &&{ return t.operator->(); } - template - auto operator[](Arg &&arg) && -> decltype(std::declval()[std::declval()]) { - return (*t)[std::forward(arg)]; - } + template + auto operator[](Arg &&arg) && -> decltype(std::declval()[std::declval()]) { + return (*t)[std::forward(arg)]; + } - T &operator*() &&{ return *t; } + T &operator*() &&{ return *t; } - operator bool() { - return !!t; - } + operator bool() { + return !!t; + } - bool operator !() { - return !t; - } - }; + bool operator !() { + return !t; + } + }; - constexpr struct emplace_t { } emplace{}; + constexpr struct emplace_t { } emplace{}; - template - struct observer_locked { - public: - observer_locked(observer_locked &&o) : t(std::move(o.t)), m(std::move(o.m)) {} - observer_locked(observer_locked const &o) : t(o.t), m(o.m) {} + template + struct observer_locked { + public: + observer_locked(observer_locked &&o) : t(std::move(o.t)), m(std::move(o.m)) {} + observer_locked(observer_locked const &o) : t(o.t), m(o.m) {} - observer_locked(M lock,T entry) : m(std::forward(lock)), t(std::forward(entry)) {} + observer_locked(M lock,T entry) : m(std::forward(lock)), t(std::forward(entry)) {} - observer_locked() = default; - ~observer_locked() = default; + observer_locked() = default; + ~observer_locked() = default; - T operator->() { - return t; - } + T operator->() { + return t; + } - T const operator->() const { - return t; - } + T const operator->() const { + return t; + } - T get() { return this->t; } - T const get() const { return this->t; } + T get() { return this->t; } + T const get() const { return this->t; } - template - std::result_of_t operator->*(F &&f) { - return std::forward(f)(t); - } + template + std::result_of_t operator->*(F &&f) { + return std::forward(f)(t); + } - template - std::result_of_t operator->*(F &&f) const { - return std::forward(f)(t); - } + template + std::result_of_t operator->*(F &&f) const { + return std::forward(f)(t); + } - observer_locked &operator=(observer_locked &&o) { - this->m = std::move(o.m); - this->t = std::move(o.t); - return *this; - } + observer_locked &operator=(observer_locked &&o) { + this->m = std::move(o.m); + this->t = std::move(o.t); + return *this; + } - observer_locked &operator=(observer_locked const &o) { - this->m = o.m; - this->t = o.t; - return *this; - } + observer_locked &operator=(observer_locked const &o) { + this->m = o.m; + this->t = o.t; + return *this; + } - observer_locked &reset() { - observer_locked empty(M(),NULL); - *this = empty; - return *this; - } - private: - M m; - T t; - }; + observer_locked &reset() { + observer_locked empty(M(),NULL); + *this = empty; + return *this; + } + private: + M m; + T t; + }; - template - struct mutex_guarded { - lock_guarded> get_locked() { - return {std::unique_lock{m}, &t}; - } + template + struct mutex_guarded { + lock_guarded> get_locked() { + return {std::unique_lock{m}, &t}; + } - lock_guarded> get_locked() const { - return {{m}, &t}; - } + lock_guarded> get_locked() const { + return {{m}, &t}; + } - lock_guarded> operator->() { - return get_locked(); - } + lock_guarded> operator->() { + return get_locked(); + } - lock_guarded> operator->() const { - return get_locked(); - } + lock_guarded> operator->() const { + return get_locked(); + } - template - std::result_of_t operator->*(F &&f) { - return std::forward(f)(*get_locked()); - } + template + std::result_of_t operator->*(F &&f) { + return std::forward(f)(*get_locked()); + } - template - std::result_of_t operator->*(F &&f) const { - return std::forward(f)(*get_locked()); - } + template + std::result_of_t operator->*(F &&f) const { + return std::forward(f)(*get_locked()); + } - template - mutex_guarded(emplace_t, Args &&...args) : t(std::forward(args)...) {} + template + mutex_guarded(emplace_t, Args &&...args) : t(std::forward(args)...) {} - mutex_guarded(mutex_guarded &&o) : t(std::move(*o.get_locked())) {} + mutex_guarded(mutex_guarded &&o) : t(std::move(*o.get_locked())) {} - mutex_guarded(mutex_guarded const &o) : t(*o.get_locked()) {} + mutex_guarded(mutex_guarded const &o) : t(*o.get_locked()) {} - mutex_guarded() = default; + mutex_guarded() = default; - ~mutex_guarded() = default; + ~mutex_guarded() = default; - mutex_guarded &operator=(mutex_guarded &&o) { - T tmp = std::move(o.get_locked()); - *get_locked() = std::move(tmp); - return *this; - } + mutex_guarded &operator=(mutex_guarded &&o) { + T tmp = std::move(o.get_locked()); + *get_locked() = std::move(tmp); + return *this; + } - mutex_guarded &operator=(mutex_guarded const &o) { - T tmp = o.get_locked(); - *get_locked() = std::move(tmp); - return *this; - } + mutex_guarded &operator=(mutex_guarded const &o) { + T tmp = o.get_locked(); + *get_locked() = std::move(tmp); + return *this; + } - private: - std::mutex m; - T t; - }; + private: + std::mutex m; + T t; + }; - /* - * ATTENTION: Not sure how/why, but this causes a double rwlock unlock sometimes (when used with std::unique_lock) - * Do not use this! - class shared_recursive_mutex { - std::shared_mutex handle; - public: - void lock(void) { - std::thread::id this_id = std::this_thread::get_id(); - if (owner == this_id) { - // recursive locking - ++count; - } else { - // normal locking - if (shared_counts->count(this_id)) {//Already shared locked, write lock is not available + /* + * ATTENTION: Not sure how/why, but this causes a double rwlock unlock sometimes (when used with std::unique_lock) + * Do not use this! + class shared_recursive_mutex { + std::shared_mutex handle; + public: + void lock(void) { + std::thread::id this_id = std::this_thread::get_id(); + if (owner == this_id) { + // recursive locking + ++count; + } else { + // normal locking + if (shared_counts->count(this_id)) {//Already shared locked, write lock is not available #ifdef WIN32 throw std::logic_error("resource_deadlock_would_occur"); #else __throw_system_error(int(errc::resource_deadlock_would_occur)); #endif - } - handle.lock(); //Now wait until everyone else has finished - owner = this_id; - count = 1; - } - } + } + handle.lock(); //Now wait until everyone else has finished + owner = this_id; + count = 1; + } + } - void unlock(void) { - std::thread::id this_id = std::this_thread::get_id(); - assert(this_id == this->owner); + void unlock(void) { + std::thread::id this_id = std::this_thread::get_id(); + assert(this_id == this->owner); - if (count > 1) { - // recursive unlocking - count--; - } else { - // normal unlocking - owner = this_id; - count = 0; - handle.unlock(); - } - } + if (count > 1) { + // recursive unlocking + count--; + } else { + // normal unlocking + owner = this_id; + count = 0; + handle.unlock(); + } + } - void lock_shared() { - std::thread::id this_id = std::this_thread::get_id(); - if(this->owner == this_id) { + void lock_shared() { + std::thread::id this_id = std::this_thread::get_id(); + if(this->owner == this_id) { #ifdef WIN32 throw std::logic_error("resource_deadlock_would_occur"); #else @@ -209,34 +209,34 @@ namespace std { #endif } - if (shared_counts->count(this_id)) { - ++(shared_counts.get_locked()[this_id]); - } else { - handle.lock_shared(); - shared_counts.get_locked()[this_id] = 1; - } - } + if (shared_counts->count(this_id)) { + ++(shared_counts.get_locked()[this_id]); + } else { + handle.lock_shared(); + shared_counts.get_locked()[this_id] = 1; + } + } - void unlock_shared() { - std::thread::id this_id = std::this_thread::get_id(); - auto it = shared_counts->find(this_id); - if (it->second > 1) { - --(it->second); - } else { - shared_counts->erase(it); - handle.unlock_shared(); - } - } + void unlock_shared() { + std::thread::id this_id = std::this_thread::get_id(); + auto it = shared_counts->find(this_id); + if (it->second > 1) { + --(it->second); + } else { + shared_counts->erase(it); + handle.unlock_shared(); + } + } - bool try_lock() { - std::thread::id this_id = std::this_thread::get_id(); - if (owner == this_id) { - // recursive locking - ++count; - return true; - } else { - // normal locking - if (shared_counts->count(this_id)){ //Already shared locked, write lock is not available + bool try_lock() { + std::thread::id this_id = std::this_thread::get_id(); + if (owner == this_id) { + // recursive locking + ++count; + return true; + } else { + // normal locking + if (shared_counts->count(this_id)){ //Already shared locked, write lock is not available #ifdef WIN32 throw std::logic_error("resource_deadlock_would_occur"); #else @@ -244,17 +244,17 @@ namespace std { #endif } - if(!handle.try_lock()) return false; + if(!handle.try_lock()) return false; - owner = this_id; - count = 1; - return true; - } - } + owner = this_id; + count = 1; + return true; + } + } - bool try_lock_shared() { - std::thread::id this_id = std::this_thread::get_id(); - if(this->owner == this_id){ + bool try_lock_shared() { + std::thread::id this_id = std::this_thread::get_id(); + if(this->owner == this_id){ #ifdef WIN32 throw std::logic_error("resource_deadlock_would_occur"); #else @@ -262,42 +262,42 @@ namespace std { #endif } - if (shared_counts->count(this_id)) { - ++(shared_counts.get_locked()[this_id]); - } else { - if(!handle.try_lock_shared()) return false; + if (shared_counts->count(this_id)) { + ++(shared_counts.get_locked()[this_id]); + } else { + if(!handle.try_lock_shared()) return false; - shared_counts.get_locked()[this_id] = 1; - } - return true; - } + shared_counts.get_locked()[this_id] = 1; + } + return true; + } - private: - std::atomic owner; - std::atomic count; - mutex_guarded> shared_counts; - }; - */ + private: + std::atomic owner; + std::atomic count; + mutex_guarded> shared_counts; + }; + */ - template - inline bool mutex_locked(T& mutex) { - return true; - try { - unique_lock lock_try(mutex, try_to_lock); /* should throw EDEADLK */ - return false; - } catch(const std::system_error& ex) { - return ex.code() == errc::resource_deadlock_would_occur; - } - } + template + inline bool mutex_locked(T& mutex) { + return true; + try { + unique_lock lock_try(mutex, try_to_lock); /* should throw EDEADLK */ + return false; + } catch(const std::system_error& ex) { + return ex.code() == errc::resource_deadlock_would_occur; + } + } - template - inline bool mutex_shared_locked(T& mutex) { - return true; - try { - shared_lock lock_try(mutex, try_to_lock); /* should throw EDEADLK */ - return false; - } catch(const std::system_error& ex) { - return ex.code() == errc::resource_deadlock_would_occur; - } - } + template + inline bool mutex_shared_locked(T& mutex) { + return true; + try { + shared_lock lock_try(mutex, try_to_lock); /* should throw EDEADLK */ + return false; + } catch(const std::system_error& ex) { + return ex.code() == errc::resource_deadlock_would_occur; + } + } } \ No newline at end of file diff --git a/src/misc/base64.cpp b/src/misc/base64.cpp index fd7483c..66a402c 100644 --- a/src/misc/base64.cpp +++ b/src/misc/base64.cpp @@ -3,24 +3,24 @@ std::string base64::decode(const char* input, size_t size) { - auto out = new unsigned char[size]; - if(base64_strict_decode((unsigned char*) input, (unsigned long) size, out, (unsigned long*) &size) != CRYPT_OK){ - std::cerr << "Invalid base 64 string '" << input << "'" << std::endl; - return ""; - } - std::string ret((char*) out, size); - delete[] out; - return ret; + auto out = new unsigned char[size]; + if(base64_strict_decode((unsigned char*) input, (unsigned long) size, out, (unsigned long*) &size) != CRYPT_OK){ + std::cerr << "Invalid base 64 string '" << input << "'" << std::endl; + return ""; + } + std::string ret((char*) out, size); + delete[] out; + return ret; } std::string base64::encode(const char* input, const unsigned long inputSize) { - auto outlen = static_cast(inputSize + (inputSize / 3.0) + 16); - auto outbuf = new unsigned char[outlen]; //Reserve output memory - if(base64_encode((unsigned char*) input, inputSize, outbuf, &outlen) != CRYPT_OK){ - std::cerr << "Invalid input '" << input << "'" << std::endl; - return ""; - } - std::string ret((char*) outbuf, outlen); - delete[] outbuf; - return ret; + auto outlen = static_cast(inputSize + (inputSize / 3.0) + 16); + auto outbuf = new unsigned char[outlen]; //Reserve output memory + if(base64_encode((unsigned char*) input, inputSize, outbuf, &outlen) != CRYPT_OK){ + std::cerr << "Invalid input '" << input << "'" << std::endl; + return ""; + } + std::string ret((char*) outbuf, outlen); + delete[] outbuf; + return ret; } \ No newline at end of file diff --git a/src/misc/digest.cpp b/src/misc/digest.cpp index 206b113..abe059c 100644 --- a/src/misc/digest.cpp +++ b/src/misc/digest.cpp @@ -1,17 +1,17 @@ #include "./digest.h" #ifdef NO_OPEN_SSL - #include + #include - #define DECLARE_DIGEST(name, digestLength) \ - void digest::tomcrypt::name(const char* input, size_t length, uint8_t* result) { \ - hash_state hash{}; \ - \ - name ##_init(&hash); \ - name ##_process(&hash, (uint8_t*) input, (unsigned long) length); \ - name ##_done(&hash, result); \ - } + #define DECLARE_DIGEST(name, digestLength) \ + void digest::tomcrypt::name(const char* input, size_t length, uint8_t* result) { \ + hash_state hash{}; \ + \ + name ##_init(&hash); \ + name ##_process(&hash, (uint8_t*) input, (unsigned long) length); \ + name ##_done(&hash, result); \ + } - DECLARE_DIGEST(sha1, SHA_DIGEST_LENGTH) - DECLARE_DIGEST(sha256, SHA256_DIGEST_LENGTH) - DECLARE_DIGEST(sha512, SHA512_DIGEST_LENGTH) + DECLARE_DIGEST(sha1, SHA_DIGEST_LENGTH) + DECLARE_DIGEST(sha256, SHA256_DIGEST_LENGTH) + DECLARE_DIGEST(sha512, SHA512_DIGEST_LENGTH) #endif diff --git a/src/misc/digest.h b/src/misc/digest.h index 1fc15fa..25c6dcd 100644 --- a/src/misc/digest.h +++ b/src/misc/digest.h @@ -6,60 +6,60 @@ #include #ifdef NO_OPEN_SSL - #define SHA_DIGEST_LENGTH (20) - #define SHA256_DIGEST_LENGTH (32) - #define SHA512_DIGEST_LENGTH (64) + #define SHA_DIGEST_LENGTH (20) + #define SHA256_DIGEST_LENGTH (32) + #define SHA512_DIGEST_LENGTH (64) - #define DECLARE_DIGEST(name, _unused_, digestLength) \ - namespace tomcrypt { \ - extern void name(const char* input, size_t length, uint8_t* result); \ - } \ - inline std::string name(const std::string& input) { \ - uint8_t result[digestLength]; \ - tomcrypt::name(input.data(), input.length(), result); \ - auto _result = std::string((const char*) result, (size_t) digestLength); \ - assert(_result.length() == digestLength); \ - return _result; \ - } \ - \ - inline std::string name(const char* input, int64_t length = -1) { \ - if(length == -1) length = strlen(input); \ - uint8_t result[digestLength]; \ - tomcrypt::name(input, length, result); \ - auto _result = std::string((const char*) result, (size_t) digestLength); \ - assert(_result.length() == digestLength); \ - return _result; \ - } \ - \ - \ - inline void name(const char* input, size_t length, uint8_t* result) { \ - tomcrypt::name(input, length, result); \ - } + #define DECLARE_DIGEST(name, _unused_, digestLength) \ + namespace tomcrypt { \ + extern void name(const char* input, size_t length, uint8_t* result); \ + } \ + inline std::string name(const std::string& input) { \ + uint8_t result[digestLength]; \ + tomcrypt::name(input.data(), input.length(), result); \ + auto _result = std::string((const char*) result, (size_t) digestLength); \ + assert(_result.length() == digestLength); \ + return _result; \ + } \ + \ + inline std::string name(const char* input, int64_t length = -1) { \ + if(length == -1) length = strlen(input); \ + uint8_t result[digestLength]; \ + tomcrypt::name(input, length, result); \ + auto _result = std::string((const char*) result, (size_t) digestLength); \ + assert(_result.length() == digestLength); \ + return _result; \ + } \ + \ + \ + inline void name(const char* input, size_t length, uint8_t* result) { \ + tomcrypt::name(input, length, result); \ + } #else - #include + #include - #define DECLARE_DIGEST(name, method, digestLength) \ - inline std::string name(const std::string& input) { \ - u_char buffer[digestLength]; \ - method((u_char*) input.data(), input.length(), buffer); \ - return std::string((const char*) buffer, (size_t) digestLength); \ - } \ - \ - inline std::string name(const char* input, ssize_t length = -1) { \ - if(length == -1) length = strlen(input); \ - return name(std::string(input, (size_t) length)); \ - } \ - \ - inline void name(const char* input, size_t length, uint8_t* result) { \ - method((u_char*) input, length, result); \ - } + #define DECLARE_DIGEST(name, method, digestLength) \ + inline std::string name(const std::string& input) { \ + u_char buffer[digestLength]; \ + method((u_char*) input.data(), input.length(), buffer); \ + return std::string((const char*) buffer, (size_t) digestLength); \ + } \ + \ + inline std::string name(const char* input, ssize_t length = -1) { \ + if(length == -1) length = strlen(input); \ + return name(std::string(input, (size_t) length)); \ + } \ + \ + inline void name(const char* input, size_t length, uint8_t* result) { \ + method((u_char*) input, length, result); \ + } #endif namespace digest { - DECLARE_DIGEST(sha1, SHA1, SHA_DIGEST_LENGTH) - DECLARE_DIGEST(sha256, SHA256, SHA256_DIGEST_LENGTH) - DECLARE_DIGEST(sha512, SHA512, SHA512_DIGEST_LENGTH) + DECLARE_DIGEST(sha1, SHA1, SHA_DIGEST_LENGTH) + DECLARE_DIGEST(sha256, SHA256, SHA256_DIGEST_LENGTH) + DECLARE_DIGEST(sha512, SHA512, SHA512_DIGEST_LENGTH) } #undef DECLARE_DIGEST diff --git a/src/misc/hex.h b/src/misc/hex.h index c3f9d2a..10e6b03 100644 --- a/src/misc/hex.h +++ b/src/misc/hex.h @@ -4,30 +4,30 @@ #include namespace hex { - inline std::string hex(const std::string& input, char beg, char end){ - assert(end - beg == 16); + inline std::string hex(const std::string& input, char beg, char end){ + assert(end - beg == 16); - int len = input.length() * 2; - char output[len]; - int idx = 0; - for (char elm : input) { - output[idx++] = static_cast(beg + ((elm >> 4) & 0x0F)); - output[idx++] = static_cast(beg + ((elm & 0x0F) >> 0)); - } + int len = input.length() * 2; + char output[len]; + int idx = 0; + for (char elm : input) { + output[idx++] = static_cast(beg + ((elm >> 4) & 0x0F)); + output[idx++] = static_cast(beg + ((elm & 0x0F) >> 0)); + } - return std::string(output, len); - } - inline std::string hex(const std::string& input){ - size_t len = input.length() * 2; - char output[len]; - size_t idx = 0; - for (char elm : input) { - auto lower = ((uint8_t) elm >> 4U) & 0xFU; - auto upper = ((uint8_t) elm & 0xFU) >> 0U; - output[idx++] = static_cast(lower > 9 ? 'a' + (lower - 9) : '0' + lower); - output[idx++] = static_cast(upper > 9 ? 'a' + (upper - 9) : '0' + upper); - } + return std::string(output, len); + } + inline std::string hex(const std::string& input){ + size_t len = input.length() * 2; + char output[len]; + size_t idx = 0; + for (char elm : input) { + auto lower = ((uint8_t) elm >> 4U) & 0xFU; + auto upper = ((uint8_t) elm & 0xFU) >> 0U; + output[idx++] = static_cast(lower > 9 ? 'a' + (lower - 9) : '0' + lower); + output[idx++] = static_cast(upper > 9 ? 'a' + (upper - 9) : '0' + upper); + } - return std::string(output, len); - } + return std::string(output, len); + } } \ No newline at end of file diff --git a/src/misc/memtracker.cpp b/src/misc/memtracker.cpp index 6218ec3..452aef1 100644 --- a/src/misc/memtracker.cpp +++ b/src/misc/memtracker.cpp @@ -24,204 +24,204 @@ //#define MEMTRACK_VERBOSE inline bool should_track_mangled(const char* mangled) { - if(strstr(mangled, "ViewEntry")) return true; - if(strstr(mangled, "ViewEntry")) return true; - if(strstr(mangled, "ClientChannelView")) return true; - if(strstr(mangled, "LinkedTreeEntry")) return true; + if(strstr(mangled, "ViewEntry")) return true; + if(strstr(mangled, "ViewEntry")) return true; + if(strstr(mangled, "ClientChannelView")) return true; + if(strstr(mangled, "LinkedTreeEntry")) return true; - return false; + return false; } using namespace std; namespace memtrack { - struct TypeInfo { - const char* name; - std::string mangled; + struct TypeInfo { + const char* name; + std::string mangled; - explicit TypeInfo(const char* name) : name(name) {} + explicit TypeInfo(const char* name) : name(name) {} - bool operator==(const TypeInfo& other) { - return other.name == this->name || strcmp(other.name, this->name) == 0; - } - bool operator!=(const TypeInfo& other) { - return ! this->operator==(other); - } + bool operator==(const TypeInfo& other) { + return other.name == this->name || strcmp(other.name, this->name) == 0; + } + bool operator!=(const TypeInfo& other) { + return ! this->operator==(other); + } - bool operator<(const TypeInfo& __rhs) const noexcept - { return this->before(__rhs); } + bool operator<(const TypeInfo& __rhs) const noexcept + { return this->before(__rhs); } - bool operator<=(const TypeInfo& __rhs) const noexcept - { return !__rhs.before(*this); } + bool operator<=(const TypeInfo& __rhs) const noexcept + { return !__rhs.before(*this); } - bool operator>(const TypeInfo& __rhs) const noexcept - { return __rhs.before(*this); } + bool operator>(const TypeInfo& __rhs) const noexcept + { return __rhs.before(*this); } - bool operator>=(const TypeInfo& __rhs) const noexcept - { return !this->before(__rhs); } + bool operator>=(const TypeInfo& __rhs) const noexcept + { return !this->before(__rhs); } - inline bool before(const TypeInfo& __arg) const _GLIBCXX_NOEXCEPT - { return (name[0] == '*' && __arg.name[0] == '*') - ? name < __arg.name - : strcmp (name, __arg.name) < 0; } + inline bool before(const TypeInfo& __arg) const _GLIBCXX_NOEXCEPT + { return (name[0] == '*' && __arg.name[0] == '*') + ? name < __arg.name + : strcmp (name, __arg.name) < 0; } - inline std::string as_mangled() { + inline std::string as_mangled() { #ifndef WIN32 - int status; - std::unique_ptr result(abi::__cxa_demangle(name, 0, 0, &status), std::free); - if(status != 0) - return "error: " + to_string(status); + int status; + std::unique_ptr result(abi::__cxa_demangle(name, 0, 0, &status), std::free); + if(status != 0) + return "error: " + to_string(status); - this->mangled = result.get(); + this->mangled = result.get(); #else //FIXME Implement! this->mangled = this->name; #endif - return this->mangled; - } - }; - class entry { - public: - /* std::string name; */ - size_t type; - void* address = nullptr; + return this->mangled; + } + }; + class entry { + public: + /* std::string name; */ + size_t type; + void* address = nullptr; - entry() {} - entry(size_t type, void* address) : type(type), address(address) {} - ~entry() {} - }; + entry() {} + entry(size_t type, void* address) : type(type), address(address) {} + ~entry() {} + }; - template - class brick { - public: - inline bool insert(size_t type, void* address) { - auto slot = free_slot(); - if(slot == N) return false; - entries[slot] = entry{type, address}; - findex = slot + 1; - return true; - } + template + class brick { + public: + inline bool insert(size_t type, void* address) { + auto slot = free_slot(); + if(slot == N) return false; + entries[slot] = entry{type, address}; + findex = slot + 1; + return true; + } - inline bool remove(size_t type, void* address) { - for(int index = 0; index < N; index++) { - auto& e = entries[index]; - if(e.address == address && e.type == type) { - e = entry{}; - findex = index; - return true; - } - } - return false; - } + inline bool remove(size_t type, void* address) { + for(int index = 0; index < N; index++) { + auto& e = entries[index]; + if(e.address == address && e.type == type) { + e = entry{}; + findex = index; + return true; + } + } + return false; + } - inline int capacity() { return N; } + inline int capacity() { return N; } - array entries; - private: - inline int free_slot() { - while (findex < N && entries[findex].address) findex++; - return findex; - } - int findex = 0; - }; - typedef brick<1024> InfoBrick; + array entries; + private: + inline int free_slot() { + while (findex < N && entries[findex].address) findex++; + return findex; + } + int findex = 0; + }; + typedef brick<1024> InfoBrick; - template - struct DefaultValued { - T value = N; - }; + template + struct DefaultValued { + T value = N; + }; - map> type_indexes; - vector bricks; - mutex bricks_lock; + map> type_indexes; + vector bricks; + mutex bricks_lock; - void allocated(const char* name, void* address) { + void allocated(const char* name, void* address) { #ifdef NO_IMPL - return; + return; #else #ifdef MEMTRACK_VERBOSE - logTrace(lstream << "[MEMORY] Allocated a new instance of '" << name << "' at " << address); + logTrace(lstream << "[MEMORY] Allocated a new instance of '" << name << "' at " << address); #endif - if(!should_track_mangled(name)) return; + if(!should_track_mangled(name)) return; - lock_guard lock(bricks_lock); - TypeInfo local_info(name); - auto& type_index = type_indexes[local_info]; - if(type_index.value == -1) { - type_index.value = type_indexes.size() - 1; - } + lock_guard lock(bricks_lock); + TypeInfo local_info(name); + auto& type_index = type_indexes[local_info]; + if(type_index.value == -1) { + type_index.value = type_indexes.size() - 1; + } - auto _value = (size_t) type_index.value; - for(auto it = bricks.begin(); it != bricks.end(); it++) - if((*it)->insert(_value, address)) return; - bricks.push_back(new InfoBrick{}); - auto success = bricks.back()->insert(type_index.value, address); - assert(success); + auto _value = (size_t) type_index.value; + for(auto it = bricks.begin(); it != bricks.end(); it++) + if((*it)->insert(_value, address)) return; + bricks.push_back(new InfoBrick{}); + auto success = bricks.back()->insert(type_index.value, address); + assert(success); #endif - } + } - void freed(const char* name, void* address) { + void freed(const char* name, void* address) { #ifdef NO_IMPL - return; + return; #else #ifdef MEMTRACK_VERBOSE - logTrace(lstream << "[MEMORY] Deallocated a instance of '" << name << "' at " << address); + logTrace(lstream << "[MEMORY] Deallocated a instance of '" << name << "' at " << address); #endif - if(!should_track_mangled(name)) return; + if(!should_track_mangled(name)) return; - lock_guard lock(bricks_lock); - TypeInfo local_info(name); - auto& type_index = type_indexes[local_info]; - if(type_index.value == -1) - type_index.value = type_indexes.size() - 1; + lock_guard lock(bricks_lock); + TypeInfo local_info(name); + auto& type_index = type_indexes[local_info]; + if(type_index.value == -1) + type_index.value = type_indexes.size() - 1; - auto _value = (size_t) type_index.value; - for (auto &brick : bricks) - if(brick->remove(_value, address)) return; - logError(lstream << "[MEMORY] Got deallocated notify, but never the allocated! (Address: " << address << " Name: " << name << ")"); + auto _value = (size_t) type_index.value; + for (auto &brick : bricks) + if(brick->remove(_value, address)) return; + logError(lstream << "[MEMORY] Got deallocated notify, but never the allocated! (Address: " << address << " Name: " << name << ")"); #endif - } + } - void statistics() { + void statistics() { #ifdef NO_IMPL - logError(LOG_GENERAL, "memtracker::statistics() does not work due compiler flags (NO_IMPL)"); - return; + logError(LOG_GENERAL, "memtracker::statistics() does not work due compiler flags (NO_IMPL)"); + return; #else - map> objects; - map mapping; + map> objects; + map mapping; - { - lock_guard lock(bricks_lock); - for(auto& brick : bricks) - for(auto& entry : brick->entries) - if(entry.address) { - objects[entry.type].push_back(entry.address); - } - for(auto& type : type_indexes) - mapping[type.second.value] = type.first.as_mangled(); - } + { + lock_guard lock(bricks_lock); + for(auto& brick : bricks) + for(auto& entry : brick->entries) + if(entry.address) { + objects[entry.type].push_back(entry.address); + } + for(auto& type : type_indexes) + mapping[type.second.value] = type.first.as_mangled(); + } - logMessage("Allocated object types: " + to_string(objects.size())); - for(const auto& entry : objects) { - logMessage(" " + mapping[entry.first] + ": " + to_string(entry.second.size())); - if (entry.second.size() < 50) { - stringstream ss; - for (int index = 0; index < entry.second.size(); index++) { - if (index % 16 == 0) { - if (index + 1 >= entry.second.size()) break; - if (index != 0) - logMessage(ss.str()); - ss = stringstream(); - ss << " "; - } - ss << entry.second[index] << " "; - } - if (!ss.str().empty()) - logMessage(ss.str()); - } else { - logMessage(""); - } - } + logMessage("Allocated object types: " + to_string(objects.size())); + for(const auto& entry : objects) { + logMessage(" " + mapping[entry.first] + ": " + to_string(entry.second.size())); + if (entry.second.size() < 50) { + stringstream ss; + for (int index = 0; index < entry.second.size(); index++) { + if (index % 16 == 0) { + if (index + 1 >= entry.second.size()) break; + if (index != 0) + logMessage(ss.str()); + ss = stringstream(); + ss << " "; + } + ss << entry.second[index] << " "; + } + if (!ss.str().empty()) + logMessage(ss.str()); + } else { + logMessage(""); + } + } #endif - } + } } \ No newline at end of file diff --git a/src/misc/memtracker.h b/src/misc/memtracker.h index fe28869..0cdc2d5 100644 --- a/src/misc/memtracker.h +++ b/src/misc/memtracker.h @@ -6,25 +6,25 @@ namespace memtrack { #define TRACK_OBJECT_ALLOCATION #ifdef TRACK_OBJECT_ALLOCATION - extern void allocated(const char* name, void* address); - extern void freed(const char* name, void* address); - template - void allocated(void* address) { allocated(typeid(T).name(), address); } + extern void allocated(const char* name, void* address); + extern void freed(const char* name, void* address); + template + void allocated(void* address) { allocated(typeid(T).name(), address); } - template - void freed(void* address) { freed(typeid(T).name(), address); } + template + void freed(void* address) { freed(typeid(T).name(), address); } - void statistics(); + void statistics(); #else - template - inline void __empty(...) { } + template + inline void __empty(...) { } - #define freed __empty - #define allocated __empty + #define freed __empty + #define allocated __empty - #define allocated_mangled __empty - #define freed_mangled __empty + #define allocated_mangled __empty + #define freed_mangled __empty - inline void statistics() {} + inline void statistics() {} #endif } \ No newline at end of file diff --git a/src/misc/net.h b/src/misc/net.h index 8c2f74b..c46eba5 100644 --- a/src/misc/net.h +++ b/src/misc/net.h @@ -18,134 +18,134 @@ #endif namespace net { - inline std::string to_string(const in6_addr& address) { - char buffer[INET6_ADDRSTRLEN]; - if(!inet_ntop(AF_INET6, (void*) &address, buffer, INET6_ADDRSTRLEN)) return ""; - return std::string(buffer); - } + inline std::string to_string(const in6_addr& address) { + char buffer[INET6_ADDRSTRLEN]; + if(!inet_ntop(AF_INET6, (void*) &address, buffer, INET6_ADDRSTRLEN)) return ""; + return std::string(buffer); + } - inline std::string to_string(const in_addr& address) { - char buffer[INET_ADDRSTRLEN]; - if(!inet_ntop(AF_INET, (void*) &address, buffer, INET_ADDRSTRLEN)) return ""; - return std::string(buffer); - } + inline std::string to_string(const in_addr& address) { + char buffer[INET_ADDRSTRLEN]; + if(!inet_ntop(AF_INET, (void*) &address, buffer, INET_ADDRSTRLEN)) return ""; + return std::string(buffer); + } - inline std::string to_string(const sockaddr_storage& address, bool port = true) { - switch(address.ss_family) { - case AF_INET: - return to_string(((sockaddr_in*) &address)->sin_addr) + (port ? ":" + std::to_string(htons(((sockaddr_in*) &address)->sin_port)) : ""); - case AF_INET6: - return to_string(((sockaddr_in6*) &address)->sin6_addr) + (port ? ":" + std::to_string(htons(((sockaddr_in6*) &address)->sin6_port)) : ""); - default: - return "unknown_type"; - } - } + inline std::string to_string(const sockaddr_storage& address, bool port = true) { + switch(address.ss_family) { + case AF_INET: + return to_string(((sockaddr_in*) &address)->sin_addr) + (port ? ":" + std::to_string(htons(((sockaddr_in*) &address)->sin_port)) : ""); + case AF_INET6: + return to_string(((sockaddr_in6*) &address)->sin6_addr) + (port ? ":" + std::to_string(htons(((sockaddr_in6*) &address)->sin6_port)) : ""); + default: + return "unknown_type"; + } + } - inline uint16_t port(const sockaddr_storage& address) { - switch(address.ss_family) { - case AF_INET: - return htons(((sockaddr_in*) &address)->sin_port); - case AF_INET6: - return htons(((sockaddr_in6*) &address)->sin6_port); - default: - return 0; - } - } + inline uint16_t port(const sockaddr_storage& address) { + switch(address.ss_family) { + case AF_INET: + return htons(((sockaddr_in*) &address)->sin_port); + case AF_INET6: + return htons(((sockaddr_in6*) &address)->sin6_port); + default: + return 0; + } + } - inline socklen_t address_size(const sockaddr_storage& address) { - switch (address.ss_family) { - case AF_INET: return sizeof(sockaddr_in); - case AF_INET6: return sizeof(sockaddr_in6); - default: return 0; - } - } + inline socklen_t address_size(const sockaddr_storage& address) { + switch (address.ss_family) { + case AF_INET: return sizeof(sockaddr_in); + case AF_INET6: return sizeof(sockaddr_in6); + default: return 0; + } + } - inline bool address_equal(const sockaddr_storage& a, const sockaddr_storage& b) { - if(a.ss_family != b.ss_family) return false; - if(a.ss_family == AF_INET) return ((sockaddr_in*) &a)->sin_addr.s_addr == ((sockaddr_in*) &b)->sin_addr.s_addr; - else if(a.ss_family == AF_INET6) { + inline bool address_equal(const sockaddr_storage& a, const sockaddr_storage& b) { + if(a.ss_family != b.ss_family) return false; + if(a.ss_family == AF_INET) return ((sockaddr_in*) &a)->sin_addr.s_addr == ((sockaddr_in*) &b)->sin_addr.s_addr; + else if(a.ss_family == AF_INET6) { #ifdef WIN32 return memcmp(((sockaddr_in6*) &a)->sin6_addr.u.Byte, ((sockaddr_in6*) &b)->sin6_addr.u.Byte, 16) == 0; #else return memcmp(((sockaddr_in6*) &a)->sin6_addr.__in6_u.__u6_addr8, ((sockaddr_in6*) &b)->sin6_addr.__in6_u.__u6_addr8, 16) == 0; #endif - } - return false; - } + } + return false; + } - inline bool address_equal_ranged(const sockaddr_storage& a, const sockaddr_storage& b, uint8_t range) { - if(a.ss_family != b.ss_family) return false; - if(a.ss_family == AF_INET) { - auto address_a = ((sockaddr_in*) &a)->sin_addr.s_addr; - auto address_b = ((sockaddr_in*) &b)->sin_addr.s_addr; + inline bool address_equal_ranged(const sockaddr_storage& a, const sockaddr_storage& b, uint8_t range) { + if(a.ss_family != b.ss_family) return false; + if(a.ss_family == AF_INET) { + auto address_a = ((sockaddr_in*) &a)->sin_addr.s_addr; + auto address_b = ((sockaddr_in*) &b)->sin_addr.s_addr; - if(range > 32) - range = 32; + if(range > 32) + range = 32; - range = (uint8_t) (32 - range); + range = (uint8_t) (32 - range); - address_a <<= range; - address_b <<= range; + address_a <<= range; + address_b <<= range; - return address_a == address_b; - } else if(a.ss_family == AF_INET6) { + return address_a == address_b; + } else if(a.ss_family == AF_INET6) { #ifdef WIN32 - throw std::runtime_error("not implemented"); + throw std::runtime_error("not implemented"); //FIXME: Implement me! #elif defined(__x86_64__) && false - static_assert(sizeof(__int128) == 16); - auto address_a = (__int128) ((sockaddr_in6*) &a)->sin6_addr.__in6_u.__u6_addr32; - auto address_b = (__int128) ((sockaddr_in6*) &b)->sin6_addr.__in6_u.__u6_addr32; + static_assert(sizeof(__int128) == 16); + auto address_a = (__int128) ((sockaddr_in6*) &a)->sin6_addr.__in6_u.__u6_addr32; + auto address_b = (__int128) ((sockaddr_in6*) &b)->sin6_addr.__in6_u.__u6_addr32; - if(range > 128) - range = 128; - range = (uint8_t) (128 - range); + if(range > 128) + range = 128; + range = (uint8_t) (128 - range); - address_a <<= range; - address_b <<= range; + address_a <<= range; + address_b <<= range; - return address_a == address_b; + return address_a == address_b; #else - static_assert(sizeof(uint64_t) == 8); + static_assert(sizeof(uint64_t) == 8); - if(range > 128) - range = 128; - range = (uint8_t) (128 - range); + if(range > 128) + range = 128; + range = (uint8_t) (128 - range); - auto address_ah = (uint64_t) (((sockaddr_in6*) &a)->sin6_addr.__in6_u.__u6_addr8 + 0); - auto address_al = (uint64_t) (((sockaddr_in6*) &a)->sin6_addr.__in6_u.__u6_addr8 + 8); - auto address_bh = (uint64_t) (((sockaddr_in6*) &b)->sin6_addr.__in6_u.__u6_addr8 + 0); - auto address_bl = (uint64_t) (((sockaddr_in6*) &b)->sin6_addr.__in6_u.__u6_addr8 + 8); + auto address_ah = (uint64_t) (((sockaddr_in6*) &a)->sin6_addr.__in6_u.__u6_addr8 + 0); + auto address_al = (uint64_t) (((sockaddr_in6*) &a)->sin6_addr.__in6_u.__u6_addr8 + 8); + auto address_bh = (uint64_t) (((sockaddr_in6*) &b)->sin6_addr.__in6_u.__u6_addr8 + 0); + auto address_bl = (uint64_t) (((sockaddr_in6*) &b)->sin6_addr.__in6_u.__u6_addr8 + 8); - if(range > 64) { - /* only lower counts */ - return (address_al << (range - 64)) == (address_bl << (range - 64)); - } else { - return address_al == address_bl &&(address_bh << (range - 64)) == (address_ah << (range - 64)); - } + if(range > 64) { + /* only lower counts */ + return (address_al << (range - 64)) == (address_bl << (range - 64)); + } else { + return address_al == address_bl &&(address_bh << (range - 64)) == (address_ah << (range - 64)); + } #endif - } - return false; - } + } + return false; + } - inline bool is_ipv6(const std::string& str) { - sockaddr_in6 sa{}; - return inet_pton(AF_INET6, str.c_str(), &(sa.sin6_addr)) != 0; - } + inline bool is_ipv6(const std::string& str) { + sockaddr_in6 sa{}; + return inet_pton(AF_INET6, str.c_str(), &(sa.sin6_addr)) != 0; + } - inline bool is_ipv4(const std::string& str) { - sockaddr_in sa{}; - return inet_pton(AF_INET, str.c_str(), &(sa.sin_addr)) != 0; - } + inline bool is_ipv4(const std::string& str) { + sockaddr_in sa{}; + return inet_pton(AF_INET, str.c_str(), &(sa.sin_addr)) != 0; + } - inline bool is_anybind(sockaddr_storage& storage) { - if(storage.ss_family == AF_INET) { - auto data = (sockaddr_in*) &storage; - return data->sin_addr.s_addr == 0; - } else if(storage.ss_family == AF_INET6) { - auto data = (sockaddr_in6*) &storage; + inline bool is_anybind(sockaddr_storage& storage) { + if(storage.ss_family == AF_INET) { + auto data = (sockaddr_in*) &storage; + return data->sin_addr.s_addr == 0; + } else if(storage.ss_family == AF_INET6) { + auto data = (sockaddr_in6*) &storage; #ifdef WIN32 auto& blocks = data->sin6_addr.u.Word; return @@ -158,103 +158,103 @@ namespace net { blocks[6] == 0 && blocks[7] == 0; #else - auto& blocks = data->sin6_addr.__in6_u.__u6_addr32; - return blocks[0] == 0 && blocks[1] == 0 && blocks[2] == 0 && blocks[3] == 0; + auto& blocks = data->sin6_addr.__in6_u.__u6_addr32; + return blocks[0] == 0 && blocks[1] == 0 && blocks[2] == 0 && blocks[3] == 0; #endif - } - return false; - } + } + return false; + } - inline bool resolve_address(const std::string& address, sockaddr_storage& result) { - if(is_ipv4(address)) { - sockaddr_in s{}; - s.sin_port = 0; - s.sin_family = AF_INET; + inline bool resolve_address(const std::string& address, sockaddr_storage& result) { + if(is_ipv4(address)) { + sockaddr_in s{}; + s.sin_port = 0; + s.sin_family = AF_INET; - auto record = gethostbyname(address.c_str()); - if(!record) - return false; - s.sin_addr.s_addr = ((in_addr*) record->h_addr)->s_addr; + auto record = gethostbyname(address.c_str()); + if(!record) + return false; + s.sin_addr.s_addr = ((in_addr*) record->h_addr)->s_addr; - memcpy(&result, &s, sizeof(s)); - return true; - } else if(is_ipv6(address)) { - sockaddr_in6 s{}; - s.sin6_family = AF_INET6; - s.sin6_port = 0; - s.sin6_flowinfo = 0; - s.sin6_scope_id = 0; + memcpy(&result, &s, sizeof(s)); + return true; + } else if(is_ipv6(address)) { + sockaddr_in6 s{}; + s.sin6_family = AF_INET6; + s.sin6_port = 0; + s.sin6_flowinfo = 0; + s.sin6_scope_id = 0; #ifdef WIN32 auto record = gethostbyname(address.c_str()); #else auto record = gethostbyname2(address.c_str(), AF_INET6); #endif - if(!record) return false; - s.sin6_addr = *(in6_addr*) record->h_addr; + if(!record) return false; + s.sin6_addr = *(in6_addr*) record->h_addr; - memcpy(&result, &s, sizeof(s)); - return true; - } else if(address == "[::]" || address == "::") { - sockaddr_in6 s{}; - s.sin6_family = AF_INET6; - s.sin6_port = 0; - s.sin6_flowinfo = 0; - s.sin6_scope_id = 0; + memcpy(&result, &s, sizeof(s)); + return true; + } else if(address == "[::]" || address == "::") { + sockaddr_in6 s{}; + s.sin6_family = AF_INET6; + s.sin6_port = 0; + s.sin6_flowinfo = 0; + s.sin6_scope_id = 0; - memcpy(&s.sin6_addr, &in6addr_any, sizeof(in6_addr)); - memcpy(&result, &s, sizeof(s)); - return true; - } + memcpy(&s.sin6_addr, &in6addr_any, sizeof(in6_addr)); + memcpy(&result, &s, sizeof(s)); + return true; + } - return false; - } + return false; + } - namespace helpers { - inline void strip(std::string& message) { - while(!message.empty()) { - if(message[0] == ' ') - message = message.substr(1); - else if(message[message.length() - 1] == ' ') - message = message.substr(0, message.length() - 1); - else break; - } - } + namespace helpers { + inline void strip(std::string& message) { + while(!message.empty()) { + if(message[0] == ' ') + message = message.substr(1); + else if(message[message.length() - 1] == ' ') + message = message.substr(0, message.length() - 1); + else break; + } + } - inline std::deque split(const std::string& message, char delimiter) { - std::deque result{}; - size_t found, index = 0; - do { - found = message.find(delimiter, index); - result.push_back(message.substr(index, found - index)); - index = found + 1; - } while(index != 0); - return result; - } - } + inline std::deque split(const std::string& message, char delimiter) { + std::deque result{}; + size_t found, index = 0; + do { + found = message.find(delimiter, index); + result.push_back(message.substr(index, found - index)); + index = found + 1; + } while(index != 0); + return result; + } + } - inline std::vector> resolve_bindings(const std::string& bindings, uint16_t port) { - auto binding_list = helpers::split(bindings, ','); - std::vector> result; - result.reserve(binding_list.size()); + inline std::vector> resolve_bindings(const std::string& bindings, uint16_t port) { + auto binding_list = helpers::split(bindings, ','); + std::vector> result; + result.reserve(binding_list.size()); - for(auto& address : binding_list) { - helpers::strip(address); + for(auto& address : binding_list) { + helpers::strip(address); - sockaddr_storage element{}; - memset(&element, 0, sizeof(element)); - if(!resolve_address(address, element)) { - result.emplace_back(address, element, "address resolve failed"); - continue; - } + sockaddr_storage element{}; + memset(&element, 0, sizeof(element)); + if(!resolve_address(address, element)) { + result.emplace_back(address, element, "address resolve failed"); + continue; + } - if(element.ss_family == AF_INET) { - ((sockaddr_in*) &element)->sin_port = htons(port); - } else if(element.ss_family == AF_INET6) { - ((sockaddr_in6*) &element)->sin6_port = htons(port); - } - result.emplace_back(address, element, ""); - } - return result; - } + if(element.ss_family == AF_INET) { + ((sockaddr_in*) &element)->sin_port = htons(port); + } else if(element.ss_family == AF_INET6) { + ((sockaddr_in6*) &element)->sin6_port = htons(port); + } + result.emplace_back(address, element, ""); + } + return result; + } } \ No newline at end of file diff --git a/src/misc/sassert.h b/src/misc/sassert.h index e291966..d0bbe48 100644 --- a/src/misc/sassert.h +++ b/src/misc/sassert.h @@ -4,12 +4,12 @@ //#define ALLOW_ASSERT #ifdef ALLOW_ASSERT - #define sassert(exp) assert(exp) + #define sassert(exp) assert(exp) #else - #define S(s) #s - #define sassert(exp) \ - do { \ - if(!(exp)) \ - logCritical(0, "Soft assertion @{}:{} '{}' failed! This could cause fatal fails!", __FILE__, __LINE__, #exp); \ - } while(0) + #define S(s) #s + #define sassert(exp) \ + do { \ + if(!(exp)) \ + logCritical(0, "Soft assertion @{}:{} '{}' failed! This could cause fatal fails!", __FILE__, __LINE__, #exp); \ + } while(0) #endif \ No newline at end of file diff --git a/src/misc/scope_guard.h b/src/misc/scope_guard.h index 74a183d..9b1055c 100644 --- a/src/misc/scope_guard.h +++ b/src/misc/scope_guard.h @@ -2,12 +2,12 @@ template struct scope_exit_callback { - public: - scope_exit_callback(callback_t&& callback) : callback(std::forward(callback)) {} - ~scope_exit_callback() { - this->callback(); - } + public: + scope_exit_callback(callback_t&& callback) : callback(std::forward(callback)) {} + ~scope_exit_callback() { + this->callback(); + } - private: - callback_t callback; + private: + callback_t callback; }; \ No newline at end of file diff --git a/src/misc/spin_lock.h b/src/misc/spin_lock.h index 4b01bc1..b33ea9d 100644 --- a/src/misc/spin_lock.h +++ b/src/misc/spin_lock.h @@ -4,36 +4,36 @@ #include #ifdef WIN32 - #define always_inline __forceinline + #define always_inline __forceinline #else #define always_inline inline __attribute__((__always_inline__)) #endif class spin_lock { - std::atomic_bool locked{false}; - public: - always_inline void lock() { - while (locked.exchange(true, std::memory_order_acquire)) - this->wait_until_release(); - } + std::atomic_bool locked{false}; + public: + always_inline void lock() { + while (locked.exchange(true, std::memory_order_acquire)) + this->wait_until_release(); + } - always_inline void wait_until_release() const { - uint8_t round = 0; - while (locked.load(std::memory_order_relaxed)) { - //Yield when we're using this lock for a longer time, which we usually not doing - if(round++ % 8 == 0) - std::this_thread::yield(); - } - } + always_inline void wait_until_release() const { + uint8_t round = 0; + while (locked.load(std::memory_order_relaxed)) { + //Yield when we're using this lock for a longer time, which we usually not doing + if(round++ % 8 == 0) + std::this_thread::yield(); + } + } - always_inline bool try_lock() { - return !locked.exchange(true, std::memory_order_acquire); - } + always_inline bool try_lock() { + return !locked.exchange(true, std::memory_order_acquire); + } - always_inline void unlock() { - locked.store(false, std::memory_order_release); - } + always_inline void unlock() { + locked.store(false, std::memory_order_release); + } }; #undef always_inline \ No newline at end of file diff --git a/src/misc/std_unique_ptr.h b/src/misc/std_unique_ptr.h index 1a51044..514b98a 100644 --- a/src/misc/std_unique_ptr.h +++ b/src/misc/std_unique_ptr.h @@ -6,33 +6,33 @@ #if __cplusplus <= 201103L namespace std { - template struct _Unique_if { - typedef unique_ptr _Single_object; - }; + template struct _Unique_if { + typedef unique_ptr _Single_object; + }; - template struct _Unique_if { - typedef unique_ptr _Unknown_bound; - }; + template struct _Unique_if { + typedef unique_ptr _Unknown_bound; + }; - template struct _Unique_if { - typedef void _Known_bound; - }; + template struct _Unique_if { + typedef void _Known_bound; + }; - template - typename _Unique_if::_Single_object - make_unique(Args&&... args) { - return unique_ptr(new T(std::forward(args)...)); - } + template + typename _Unique_if::_Single_object + make_unique(Args&&... args) { + return unique_ptr(new T(std::forward(args)...)); + } - template - typename _Unique_if::_Unknown_bound - make_unique(size_t n) { - typedef typename remove_extent::type U; - return unique_ptr(new U[n]()); - } + template + typename _Unique_if::_Unknown_bound + make_unique(size_t n) { + typedef typename remove_extent::type U; + return unique_ptr(new U[n]()); + } - template - typename _Unique_if::_Known_bound - make_unique(Args&&...) = delete; + template + typename _Unique_if::_Known_bound + make_unique(Args&&...) = delete; } #endif \ No newline at end of file diff --git a/src/misc/strobf.h b/src/misc/strobf.h index d7ab1ba..68c5420 100644 --- a/src/misc/strobf.h +++ b/src/misc/strobf.h @@ -5,192 +5,192 @@ #include namespace str_obf { - namespace internal { - template - struct message { - /* helper to access the types */ - static constexpr auto _size = size; - using _char_t = char_t; - using _key_t = key_t; + namespace internal { + template + struct message { + /* helper to access the types */ + static constexpr auto _size = size; + using _char_t = char_t; + using _key_t = key_t; - /* memory */ - std::array buffer{0}; - key_t key{}; + /* memory */ + std::array buffer{0}; + key_t key{}; - /* some memory access helpers */ - std::string_view string_view() const noexcept { return {this->buffer.begin(), this->length}; } - std::string string() const { return {this->buffer.begin(), this->length}; } - const char* c_str() const noexcept { return &this->buffer[0]; } - }; + /* some memory access helpers */ + std::string_view string_view() const noexcept { return {this->buffer.begin(), this->length}; } + std::string string() const { return {this->buffer.begin(), this->length}; } + const char* c_str() const noexcept { return &this->buffer[0]; } + }; - constexpr auto time_seed() noexcept { - std::uint64_t shifted = 0; + constexpr auto time_seed() noexcept { + std::uint64_t shifted = 0; - for( const auto c : __TIME__ ) - { - shifted <<= 8; - shifted |= c; - } + for( const auto c : __TIME__ ) + { + shifted <<= 8; + shifted |= c; + } - return shifted; - } + return shifted; + } - constexpr uint64_t string_hash(const char* str, int h = 0) noexcept { - return !str[h] ? 5381 : (string_hash(str, h + 1) * 33) ^ str[h]; - } + constexpr uint64_t string_hash(const char* str, int h = 0) noexcept { + return !str[h] ? 5381 : (string_hash(str, h + 1) * 33) ^ str[h]; + } #ifdef WIN32 - #pragma warning(disable: 4146) // unary minus operator applied to unsigned type, result still unsigned + #pragma warning(disable: 4146) // unary minus operator applied to unsigned type, result still unsigned #endif - constexpr std::uint32_t rng32_next(std::uint64_t& state, const std::uint32_t& inc) noexcept { - std::uint64_t oldstate = state; - // Advance internal state - state = oldstate * 6364136223846793005ULL + (inc | 1UL); - // Calculate output function (XSH RR), uses old state for max ILP - std::uint32_t xorshifted = (uint32_t) (((oldstate >> 18u) ^ oldstate) >> 27u); - std::uint32_t rot = oldstate >> 59u; - return (xorshifted >> rot) | (xorshifted << ((-rot) & 31)); - } + constexpr std::uint32_t rng32_next(std::uint64_t& state, const std::uint32_t& inc) noexcept { + std::uint64_t oldstate = state; + // Advance internal state + state = oldstate * 6364136223846793005ULL + (inc | 1UL); + // Calculate output function (XSH RR), uses old state for max ILP + std::uint32_t xorshifted = (uint32_t) (((oldstate >> 18u) ^ oldstate) >> 27u); + std::uint32_t rot = oldstate >> 59u; + return (xorshifted >> rot) | (xorshifted << ((-rot) & 31)); + } #ifdef WIN32 - #pragma warning(default: 4146) // unary minus operator applied to unsigned type, result still unsigned + #pragma warning(default: 4146) // unary minus operator applied to unsigned type, result still unsigned #endif - /* we use a buffer dividable by 8 so the compiler could do crazy shit, when loading (moving) the characters */ - constexpr size_t recommand_message_buffer(size_t message_size) noexcept { - return (message_size & 0xFFFFFFF8) + ((message_size & 0x7) > 0 ? 8 : 0); - } - } + /* we use a buffer dividable by 8 so the compiler could do crazy shit, when loading (moving) the characters */ + constexpr size_t recommand_message_buffer(size_t message_size) noexcept { + return (message_size & 0xFFFFFFF8) + ((message_size & 0x7) > 0 ? 8 : 0); + } + } - template - constexpr inline void crypt(char_t* begin, size_t length, const key_t& key) noexcept { - static_assert(sizeof(char_t) == 1, "Currently only 8 bit supported"); - if(length == 0) return; + template + constexpr inline void crypt(char_t* begin, size_t length, const key_t& key) noexcept { + static_assert(sizeof(char_t) == 1, "Currently only 8 bit supported"); + if(length == 0) return; - auto kbegin = std::begin(key); - auto kend = std::end(key); - if(kbegin == kend) return; + auto kbegin = std::begin(key); + auto kend = std::end(key); + if(kbegin == kend) return; - auto it = kbegin; + auto it = kbegin; - auto left = length; + auto left = length; #ifdef __clang__ - /* - * Enforce clang here to not evaluate this loop at compile time as long its not called in a constexpr context! - * We lose compiler opts. here a bit, but cases where a xor was made over larger than 8 bit registers were really rare! - */ - #pragma nounroll + /* + * Enforce clang here to not evaluate this loop at compile time as long its not called in a constexpr context! + * We lose compiler opts. here a bit, but cases where a xor was made over larger than 8 bit registers were really rare! + */ + #pragma nounroll #endif - while(left-- > 0) { - if(it == kend) - it = kbegin; + while(left-- > 0) { + if(it == kend) + it = kbegin; - *begin ^= *it; + *begin ^= *it; - it++; - begin++; - } - } + it++; + begin++; + } + } - template - constexpr inline auto encode(const char_t(&message)[message_size], const key_t& key) noexcept { - constexpr auto message_buffer_size = internal::recommand_message_buffer(message_size); - internal::message result{}; - result.key = key; + template + constexpr inline auto encode(const char_t(&message)[message_size], const key_t& key) noexcept { + constexpr auto message_buffer_size = internal::recommand_message_buffer(message_size); + internal::message result{}; + result.key = key; - { - auto bit = result.buffer.begin(); - auto mit = message; + { + auto bit = result.buffer.begin(); + auto mit = message; - size_t index = message_size; - while(index-- > 0) - *bit++ = *mit++; + size_t index = message_size; + while(index-- > 0) + *bit++ = *mit++; - size_t padding = message_buffer_size - message_size; - if(padding) { /* to make the string end less obvious we add some noise here (it does not harm user performance) */ - std::uint64_t rng_seed = internal::time_seed() ^ internal::string_hash(message, 0); - std::uint64_t rng_base = rng_seed; - while(padding-- > 0) - *bit++ = internal::rng32_next(rng_base, (uint32_t) rng_seed) & 0xFFUL; - } - } + size_t padding = message_buffer_size - message_size; + if(padding) { /* to make the string end less obvious we add some noise here (it does not harm user performance) */ + std::uint64_t rng_seed = internal::time_seed() ^ internal::string_hash(message, 0); + std::uint64_t rng_base = rng_seed; + while(padding-- > 0) + *bit++ = internal::rng32_next(rng_base, (uint32_t) rng_seed) & 0xFFUL; + } + } - crypt(result.buffer.data(), message_size, key); - return result; - } + crypt(result.buffer.data(), message_size, key); + return result; + } - template - constexpr inline auto str_length(const char_t(&message)[length]) noexcept { return length; } + template + constexpr inline auto str_length(const char_t(&message)[length]) noexcept { return length; } - template - inline std::string decode(const internal::message& message) { - std::string result{}; - result.resize(message_size); + template + inline std::string decode(const internal::message& message) { + std::string result{}; + result.resize(message_size); - memcpy(result.data(), message.buffer.begin(), message_size); - crypt(result.data(), message_size, message.key); + memcpy(result.data(), message.buffer.begin(), message_size); + crypt(result.data(), message_size, message.key); - return result; - } + return result; + } - constexpr inline size_t generate_key_length(std::uint64_t seed, size_t max_size) noexcept { - if(max_size <= 8) return max_size; /* We dont need a longer key then the message itself. As well compiler opt. doesn't matter here */ - if(max_size > 64) max_size = 64; + constexpr inline size_t generate_key_length(std::uint64_t seed, size_t max_size) noexcept { + if(max_size <= 8) return max_size; /* We dont need a longer key then the message itself. As well compiler opt. doesn't matter here */ + if(max_size > 64) max_size = 64; - std::uint64_t rng_base = seed; - size_t length = 0; - do { - length = (size_t) ((internal::rng32_next(rng_base, (uint32_t) seed) >> 12UL) & 0xFFUL); - } while(length < 8 || length >= max_size); + std::uint64_t rng_base = seed; + size_t length = 0; + do { + length = (size_t) ((internal::rng32_next(rng_base, (uint32_t) seed) >> 12UL) & 0xFFUL); + } while(length < 8 || length >= max_size); - /* it does not really matter if we have a 8 byte aligned number here, because we iterate so or so byte for byte */ - return length; - } + /* it does not really matter if we have a 8 byte aligned number here, because we iterate so or so byte for byte */ + return length; + } - template - constexpr inline auto generate_key(const char* _str_seed) noexcept { - std::uint64_t rng_seed = internal::time_seed() ^ internal::string_hash(_str_seed, 0) ^ line_number; - std::uint64_t rng_base = rng_seed; + template + constexpr inline auto generate_key(const char* _str_seed) noexcept { + std::uint64_t rng_seed = internal::time_seed() ^ internal::string_hash(_str_seed, 0) ^ line_number; + std::uint64_t rng_base = rng_seed; - constexpr size_t key_length = generate_key_length(internal::time_seed() ^ (line_number << 37UL), max_size); - std::array result{}; - for(auto& it : result) - it = (internal::rng32_next(rng_base, (uint32_t) rng_seed) >> 16UL) & 0xFFUL; - return result; - } + constexpr size_t key_length = generate_key_length(internal::time_seed() ^ (line_number << 37UL), max_size); + std::array result{}; + for(auto& it : result) + it = (internal::rng32_next(rng_base, (uint32_t) rng_seed) >> 16UL) & 0xFFUL; + return result; + } - template - struct decode_helper { - const message& encoded; - std::array buffer{0}; - bool decoded = false; /* a trivial check which (if this only gets used once) the compiler could evaluate */ + template + struct decode_helper { + const message& encoded; + std::array buffer{0}; + bool decoded = false; /* a trivial check which (if this only gets used once) the compiler could evaluate */ #ifndef _MSC_VER /* else if you call string_view() or string() it wound inline this method */ - __attribute__((always_inline)) inline + __attribute__((always_inline)) inline #else - __forceinline + __forceinline #endif - const char* c_str() noexcept { - if(!this->decoded) { - memcpy(this->buffer.data(), this->encoded.buffer.data(), message::_size); - crypt< - typename message::_char_t, - typename message::_key_t - >((typename message::_char_t*) &this->buffer[0], message::_size, this->encoded.key); - this->decoded = true; - } + const char* c_str() noexcept { + if(!this->decoded) { + memcpy(this->buffer.data(), this->encoded.buffer.data(), message::_size); + crypt< + typename message::_char_t, + typename message::_key_t + >((typename message::_char_t*) &this->buffer[0], message::_size, this->encoded.key); + this->decoded = true; + } - return &this->buffer[0]; - } + return &this->buffer[0]; + } - inline std::string_view string_view() noexcept { - return {this->c_str(), message::_size - 1}; - } + inline std::string_view string_view() noexcept { + return {this->c_str(), message::_size - 1}; + } - inline std::string string() { return {this->c_str(), message::_size - 1}; } + inline std::string string() { return {this->c_str(), message::_size - 1}; } - //operator const char*() noexcept { return this->c_str(); } - }; + //operator const char*() noexcept { return this->c_str(); } + }; } #define strobf_define(variable_name, string) \ @@ -200,6 +200,6 @@ constexpr auto variable_name = ::str_obf::encode(string, str_obf::generate_key<_ #define strobf(message) \ (([]{ \ - static strobf_define(_, message); \ - return strobf_val(_); \ + static strobf_define(_, message); \ + return strobf_val(_); \ })()) diff --git a/src/misc/time.cpp b/src/misc/time.cpp index 24d80d2..697ba1a 100644 --- a/src/misc/time.cpp +++ b/src/misc/time.cpp @@ -6,8 +6,8 @@ using namespace std; using namespace chrono; struct TimeEntry { - std::string indice; - std::function parser; + std::string indice; + std::function parser; }; auto parsers = std::vector({ @@ -20,40 +20,40 @@ auto parsers = std::vector({ }); std::chrono::nanoseconds period::parse(const std::string& input, std::string& error) { - nanoseconds result{}; + nanoseconds result{}; - size_t index = 0; - do { - auto found = input.find(':', index); - auto str = input.substr(index, found - index); + size_t index = 0; + do { + auto found = input.find(':', index); + auto str = input.substr(index, found - index); - auto indiceIndex = str.find_first_not_of("0123456789"); - if(indiceIndex == std::string::npos) { - error = "Missing indice for " + str + " at " + to_string(index); - return nanoseconds(0); - } - auto indice = str.substr(indiceIndex); - auto number = str.substr(0, indiceIndex); + auto indiceIndex = str.find_first_not_of("0123456789"); + if(indiceIndex == std::string::npos) { + error = "Missing indice for " + str + " at " + to_string(index); + return nanoseconds(0); + } + auto indice = str.substr(indiceIndex); + auto number = str.substr(0, indiceIndex); - bool foundIndice = false; - for(const auto& parser : parsers) { - if(parser.indice == indice) { - if(number.length() == 0) { - error = "Invalid number at " + to_string(index); - return nanoseconds(0); - } - result += parser.parser(number); - foundIndice = true; - break; - } - } - if(!foundIndice) { - error = "Invalid indice for " + str + " at " + to_string(index + indiceIndex); - return nanoseconds(0); - } + bool foundIndice = false; + for(const auto& parser : parsers) { + if(parser.indice == indice) { + if(number.length() == 0) { + error = "Invalid number at " + to_string(index); + return nanoseconds(0); + } + result += parser.parser(number); + foundIndice = true; + break; + } + } + if(!foundIndice) { + error = "Invalid indice for " + str + " at " + to_string(index + indiceIndex); + return nanoseconds(0); + } - index = found + 1; - } while(index != 0); + index = found + 1; + } while(index != 0); - return result; + return result; } \ No newline at end of file diff --git a/src/misc/time.h b/src/misc/time.h index 16076df..f209b7d 100644 --- a/src/misc/time.h +++ b/src/misc/time.h @@ -5,5 +5,5 @@ #include namespace period { - std::chrono::nanoseconds parse(const std::string&, std::string&); + std::chrono::nanoseconds parse(const std::string&, std::string&); } \ No newline at end of file diff --git a/src/misc/timer.h b/src/misc/timer.h index 35a8d02..299aa23 100644 --- a/src/misc/timer.h +++ b/src/misc/timer.h @@ -2,50 +2,50 @@ #ifndef TIMING_DISABLED - #define TIMING_REPORT(expression) \ - expression + #define TIMING_REPORT(expression) \ + expression - #define TIMING_START(_name) \ - struct { \ - struct entry { \ - std::string name; \ - std::chrono::system_clock::time_point ts; \ - }; \ - \ - std::string name; \ - std::chrono::system_clock::time_point begin; \ - std::chrono::system_clock::time_point end; \ - std::deque timings; \ - } _name ##_timings; \ - _name ##_timings.begin = std::chrono::system_clock::now(); \ + #define TIMING_START(_name) \ + struct { \ + struct entry { \ + std::string name; \ + std::chrono::system_clock::time_point ts; \ + }; \ + \ + std::string name; \ + std::chrono::system_clock::time_point begin; \ + std::chrono::system_clock::time_point end; \ + std::deque timings; \ + } _name ##_timings; \ + _name ##_timings.begin = std::chrono::system_clock::now(); \ - #define TIMING_STEP(name, step) \ - name ##_timings.timings.push_back({step, std::chrono::system_clock::now()}); + #define TIMING_STEP(name, step) \ + name ##_timings.timings.push_back({step, std::chrono::system_clock::now()}); - #define TIMING_FINISH_U(_name, unit, unit_name) \ - ([&](){ \ - _name ##_timings.end = std::chrono::system_clock::now(); \ - std::string result; \ - result = "timings for " + _name ##_timings.name + ": "; \ - result += std::to_string(std::chrono::duration_cast(_name ##_timings.end - _name ##_timings.begin).count()) + unit_name; \ - \ - auto tp = _name ##_timings.begin; \ - for(const auto& entry : _name ##_timings.timings) { \ - result += "\n "; \ - result += "- " + entry.name + ": "; \ - result += "@" + std::to_string(std::chrono::duration_cast(entry.ts - _name ##_timings.begin).count()) + unit_name; \ - result += ": " + std::to_string(std::chrono::duration_cast(entry.ts - tp).count()) + unit_name; \ - tp = entry.ts; \ - } \ - return result; \ - })() + #define TIMING_FINISH_U(_name, unit, unit_name) \ + ([&](){ \ + _name ##_timings.end = std::chrono::system_clock::now(); \ + std::string result; \ + result = "timings for " + _name ##_timings.name + ": "; \ + result += std::to_string(std::chrono::duration_cast(_name ##_timings.end - _name ##_timings.begin).count()) + unit_name; \ + \ + auto tp = _name ##_timings.begin; \ + for(const auto& entry : _name ##_timings.timings) { \ + result += "\n "; \ + result += "- " + entry.name + ": "; \ + result += "@" + std::to_string(std::chrono::duration_cast(entry.ts - _name ##_timings.begin).count()) + unit_name; \ + result += ": " + std::to_string(std::chrono::duration_cast(entry.ts - tp).count()) + unit_name; \ + tp = entry.ts; \ + } \ + return result; \ + })() - #define TIMING_FINISH(_name) TIMING_FINISH_U(_name, milliseconds, "ms") + #define TIMING_FINISH(_name) TIMING_FINISH_U(_name, milliseconds, "ms") #else - #define TIMING_REPORT(expression) - #define TIMING_START(_name) - #define TIMING_STEP(name, step) - #define TIMING_FINISH_U(_name, unit, unit_name) - #define TIMING_FINISH(_name) + #define TIMING_REPORT(expression) + #define TIMING_START(_name) + #define TIMING_STEP(name, step) + #define TIMING_FINISH_U(_name, unit, unit_name) + #define TIMING_FINISH(_name) #endif /* FIX the "backslash-newline at end of file" warning */ diff --git a/src/protocol/AcknowledgeManager.cpp b/src/protocol/AcknowledgeManager.cpp index 397605d..779f332 100644 --- a/src/protocol/AcknowledgeManager.cpp +++ b/src/protocol/AcknowledgeManager.cpp @@ -11,147 +11,147 @@ using namespace std::chrono; AcknowledgeManager::AcknowledgeManager() {} AcknowledgeManager::~AcknowledgeManager() { - { - lock_guard lock(this->entry_lock); - for(const auto& entry : this->entries) - if(entry->acknowledge_listener) - entry->acknowledge_listener->executionFailed("deleted"); - this->entries.clear(); - } + { + lock_guard lock(this->entry_lock); + for(const auto& entry : this->entries) + if(entry->acknowledge_listener) + entry->acknowledge_listener->executionFailed("deleted"); + this->entries.clear(); + } } void AcknowledgeManager::reset() { - { - lock_guard lock(this->entry_lock); - for(const auto& entry : this->entries) - if(entry->acknowledge_listener) - entry->acknowledge_listener->executionFailed("reset"); - this->entries.clear(); - } + { + lock_guard lock(this->entry_lock); + for(const auto& entry : this->entries) + if(entry->acknowledge_listener) + entry->acknowledge_listener->executionFailed("reset"); + this->entries.clear(); + } } size_t AcknowledgeManager::awaiting_acknowledge() { - lock_guard lock(this->entry_lock); - return this->entries.size(); + lock_guard lock(this->entry_lock); + return this->entries.size(); } void AcknowledgeManager::process_packet(ts::protocol::BasicPacket &packet) { - if(!packet.type().requireAcknowledge()) return; + if(!packet.type().requireAcknowledge()) return; - auto entry = make_shared(); - entry->acknowledge_listener = std::move(packet.getListener()); + auto entry = make_shared(); + entry->acknowledge_listener = std::move(packet.getListener()); - entry->buffer = packet.buffer(); + entry->buffer = packet.buffer(); - entry->resend_count = 0; - entry->resend_period = milliseconds((int) ceil(this->average_response * 3/2)); - entry->first_send = system_clock::now(); - entry->next_resend = entry->first_send + entry->resend_period; + entry->resend_count = 0; + entry->resend_period = milliseconds((int) ceil(this->average_response * 3/2)); + entry->first_send = system_clock::now(); + entry->next_resend = entry->first_send + entry->resend_period; - entry->packet_type = packet.type().type(); - entry->packet_id = packet.packetId(); + entry->packet_type = packet.type().type(); + entry->packet_id = packet.packetId(); - entry->acknowledged = false; - entry->send_count = 1; - { - lock_guard lock(this->entry_lock); - this->entries.push_front(std::move(entry)); - } + entry->acknowledged = false; + entry->send_count = 1; + { + lock_guard lock(this->entry_lock); + this->entries.push_front(std::move(entry)); + } } bool AcknowledgeManager::process_acknowledge(const ts::protocol::BasicPacket &packet, std::string& error) { - PacketType target_type = PacketType::UNDEFINED; - uint16_t target_id = 0; + PacketType target_type = PacketType::UNDEFINED; + uint16_t target_id = 0; - if(packet.type().type() == PacketType::ACK_LOW) target_type = PacketType::COMMAND_LOW; - else if(packet.type().type() == PacketType::ACK) target_type = PacketType::COMMAND; - target_id = be2le16((char*) packet.data().data_ptr()); - //debugMessage(0, "Got ack for {} {}", target_type, target_id); + if(packet.type().type() == PacketType::ACK_LOW) target_type = PacketType::COMMAND_LOW; + else if(packet.type().type() == PacketType::ACK) target_type = PacketType::COMMAND; + target_id = be2le16((char*) packet.data().data_ptr()); + //debugMessage(0, "Got ack for {} {}", target_type, target_id); - if(target_type == PacketType::UNDEFINED) { - error = "Invalid packet type (" + to_string(target_type) + ")"; - return false; - } + if(target_type == PacketType::UNDEFINED) { + error = "Invalid packet type (" + to_string(target_type) + ")"; + return false; + } - std::shared_ptr entry; - { - lock_guard lock(this->entry_lock); - for(auto it = this->entries.begin(); it != this->entries.end(); it++) { - if((*it)->packet_type == target_type && (*it)->packet_id == target_id) { - entry = *it; - entry->send_count--; - if(entry->send_count == 0) - this->entries.erase(it); - break; - } - } - } - if(!entry) { - error = "Missing packet id (" + to_string(target_id) + ")"; - return false; - } + std::shared_ptr entry; + { + lock_guard lock(this->entry_lock); + for(auto it = this->entries.begin(); it != this->entries.end(); it++) { + if((*it)->packet_type == target_type && (*it)->packet_id == target_id) { + entry = *it; + entry->send_count--; + if(entry->send_count == 0) + this->entries.erase(it); + break; + } + } + } + if(!entry) { + error = "Missing packet id (" + to_string(target_id) + ")"; + return false; + } - auto time = system_clock::now() - entry->next_resend + entry->resend_period; - auto ms_time = duration_cast(time).count(); - if(ms_time > 5) { - this->average_response = this->average_response * .80 + ms_time * .2; - } + auto time = system_clock::now() - entry->next_resend + entry->resend_period; + auto ms_time = duration_cast(time).count(); + if(ms_time > 5) { + this->average_response = this->average_response * .80 + ms_time * .2; + } - entry->acknowledged = true; - if(entry->acknowledge_listener) - entry->acknowledge_listener->executionSucceed(true); - entry->acknowledge_listener.reset(); + entry->acknowledged = true; + if(entry->acknowledge_listener) + entry->acknowledge_listener->executionSucceed(true); + entry->acknowledge_listener.reset(); - return true; + return true; } ssize_t AcknowledgeManager::execute_resend(const system_clock::time_point& now , std::chrono::system_clock::time_point &next_resend,std::deque& buffers, string& error) { - ssize_t resend_count = 0; + ssize_t resend_count = 0; - deque> need_resend; - { - deque> erase; + deque> need_resend; + { + deque> erase; - lock_guard lock(this->entry_lock); - for (auto &entry : this->entries) { - if(!entry->acknowledged && entry->next_resend <= now) { - entry->resend_period = entry->resend_period + milliseconds((int) ceil(this->average_response * 2)); - if(entry->resend_period.count() > 1000) - entry->resend_period = milliseconds(1000); - else if(entry->resend_period.count() < 25) - entry->resend_period = milliseconds(25); + lock_guard lock(this->entry_lock); + for (auto &entry : this->entries) { + if(!entry->acknowledged && entry->next_resend <= now) { + entry->resend_period = entry->resend_period + milliseconds((int) ceil(this->average_response * 2)); + if(entry->resend_period.count() > 1000) + entry->resend_period = milliseconds(1000); + else if(entry->resend_period.count() < 25) + entry->resend_period = milliseconds(25); - entry->next_resend = now + entry->resend_period; - need_resend.push_front(entry); - } - if(entry->acknowledged) { - if(entry->next_resend + entry->resend_period <= now) { //Timeout for may (more acknowledges) - erase.push_back(entry); - } - } else { - if(next_resend > entry->next_resend) - next_resend = entry->next_resend; - } - } + entry->next_resend = now + entry->resend_period; + need_resend.push_front(entry); + } + if(entry->acknowledged) { + if(entry->next_resend + entry->resend_period <= now) { //Timeout for may (more acknowledges) + erase.push_back(entry); + } + } else { + if(next_resend > entry->next_resend) + next_resend = entry->next_resend; + } + } - for(const auto& e : erase) { - auto it = find(this->entries.begin(), this->entries.end(), e); - if(it != this->entries.end()) - this->entries.erase(it); - } - } + for(const auto& e : erase) { + auto it = find(this->entries.begin(), this->entries.end(), e); + if(it != this->entries.end()) + this->entries.erase(it); + } + } - for(const auto& packet : need_resend) { - if(packet->resend_count > 15 && packet->first_send + seconds(15) < now) { //FIXME configurable - error = "Failed to receive acknowledge for packet " + to_string(packet->packet_id) + " of type " + PacketTypeInfo::fromid(packet->packet_type).name(); - return -1; - } + for(const auto& packet : need_resend) { + if(packet->resend_count > 15 && packet->first_send + seconds(15) < now) { //FIXME configurable + error = "Failed to receive acknowledge for packet " + to_string(packet->packet_id) + " of type " + PacketTypeInfo::fromid(packet->packet_type).name(); + return -1; + } - resend_count++; - packet->resend_count++; - packet->send_count++; - buffers.push_back(packet->buffer); - } + resend_count++; + packet->resend_count++; + packet->send_count++; + buffers.push_back(packet->buffer); + } - return resend_count; + return resend_count; } \ No newline at end of file diff --git a/src/protocol/AcknowledgeManager.h b/src/protocol/AcknowledgeManager.h index 3e87ac6..1736797 100644 --- a/src/protocol/AcknowledgeManager.h +++ b/src/protocol/AcknowledgeManager.h @@ -5,47 +5,47 @@ #define DEBUG_ACKNOWLEDGE namespace ts { - namespace connection { - class VoiceClientConnection; - class AcknowledgeManager { - struct Entry { - uint16_t packet_id = 0; - uint8_t packet_type = 0xFF; - uint8_t resend_count = 0; - bool acknowledged : 1; - uint8_t send_count : 7; + namespace connection { + class VoiceClientConnection; + class AcknowledgeManager { + struct Entry { + uint16_t packet_id = 0; + uint8_t packet_type = 0xFF; + uint8_t resend_count = 0; + bool acknowledged : 1; + uint8_t send_count : 7; - pipes::buffer buffer; - std::chrono::system_clock::time_point first_send; - std::chrono::system_clock::time_point next_resend; - std::chrono::milliseconds resend_period; + pipes::buffer buffer; + std::chrono::system_clock::time_point first_send; + std::chrono::system_clock::time_point next_resend; + std::chrono::milliseconds resend_period; - std::unique_ptr> acknowledge_listener; - }; - public: - AcknowledgeManager(); - virtual ~AcknowledgeManager(); + std::unique_ptr> acknowledge_listener; + }; + public: + AcknowledgeManager(); + virtual ~AcknowledgeManager(); - size_t awaiting_acknowledge(); - void reset(); + size_t awaiting_acknowledge(); + void reset(); - void process_packet(ts::protocol::BasicPacket& /* packet */); - bool process_acknowledge(const ts::protocol::BasicPacket& /* packet */, std::string& /* error */); + void process_packet(ts::protocol::BasicPacket& /* packet */); + bool process_acknowledge(const ts::protocol::BasicPacket& /* packet */, std::string& /* error */); - ssize_t execute_resend( - const std::chrono::system_clock::time_point& /* now */, - std::chrono::system_clock::time_point& /* next resend */, - std::deque& /* buffers to resend */, - std::string& /* error */ - ); - private: - std::recursive_mutex entry_lock; - std::deque> entries; + ssize_t execute_resend( + const std::chrono::system_clock::time_point& /* now */, + std::chrono::system_clock::time_point& /* next resend */, + std::deque& /* buffers to resend */, + std::string& /* error */ + ); + private: + std::recursive_mutex entry_lock; + std::deque> entries; - std::chrono::milliseconds resend_delay{500}; + std::chrono::milliseconds resend_delay{500}; - double average_response = 20; - }; - } + double average_response = 20; + }; + } } \ No newline at end of file diff --git a/src/protocol/CompressionHandler.cpp b/src/protocol/CompressionHandler.cpp index 6ed5afd..ea12821 100644 --- a/src/protocol/CompressionHandler.cpp +++ b/src/protocol/CompressionHandler.cpp @@ -11,70 +11,70 @@ using namespace ts::connection; using namespace std; bool CompressionHandler::compress(protocol::BasicPacket* packet, std::string &error) { - //// "Always allocate size + 400 bytes for the destination buffer when compressing." <= http://www.quicklz.com/manual.html - auto packet_payload = packet->data(); - auto header_length = packet->length() - packet_payload.length(); + //// "Always allocate size + 400 bytes for the destination buffer when compressing." <= http://www.quicklz.com/manual.html + auto packet_payload = packet->data(); + auto header_length = packet->length() - packet_payload.length(); - size_t max_compressed_payload_size = max(min(packet_payload.length() * 2, (size_t) (packet_payload.length() + 400ULL)), (size_t) 24ULL); /* at least 12 bytes (QLZ header) */ - auto target_buffer = buffer::allocate_buffer(max_compressed_payload_size + header_length); + size_t max_compressed_payload_size = max(min(packet_payload.length() * 2, (size_t) (packet_payload.length() + 400ULL)), (size_t) 24ULL); /* at least 12 bytes (QLZ header) */ + auto target_buffer = buffer::allocate_buffer(max_compressed_payload_size + header_length); - qlz_state_compress state_compress{}; - size_t actual_length = qlz_compress(packet_payload.data_ptr(), (char*) &target_buffer[header_length], packet_payload.length(), &state_compress); - if(actual_length > max_compressed_payload_size) { - logCritical(0, "Buffer overflow! Compressed data is longer than expected. (Expected: {}, Written: {}, Allocated block size: {})", - max_compressed_payload_size, - actual_length, - target_buffer.capacity() - ); - error = "overflow"; - return false; - } - if(actual_length <= 0){ - error = "Cloud not compress packet"; - return false; - } + qlz_state_compress state_compress{}; + size_t actual_length = qlz_compress(packet_payload.data_ptr(), (char*) &target_buffer[header_length], packet_payload.length(), &state_compress); + if(actual_length > max_compressed_payload_size) { + logCritical(0, "Buffer overflow! Compressed data is longer than expected. (Expected: {}, Written: {}, Allocated block size: {})", + max_compressed_payload_size, + actual_length, + target_buffer.capacity() + ); + error = "overflow"; + return false; + } + if(actual_length <= 0){ + error = "Cloud not compress packet"; + return false; + } - memcpy(target_buffer.data_ptr(), packet->buffer().data_ptr(), header_length); - packet->buffer(target_buffer.range(0, actual_length + header_length)); - return true; + memcpy(target_buffer.data_ptr(), packet->buffer().data_ptr(), header_length); + packet->buffer(target_buffer.range(0, actual_length + header_length)); + return true; } bool CompressionHandler::decompress(protocol::BasicPacket* packet, std::string &error) { - qlz_state_decompress state_decompress{}; + qlz_state_decompress state_decompress{}; - size_t expected_length = qlz_size_decompressed((char*) packet->data().data_ptr()); - if(expected_length > this->max_packet_size){ //Max 16MB. (97% Compression!) - error = "Invalid packet size. (Calculated target length of " + to_string(expected_length) + ". Max length: " + to_string(this->max_packet_size) + ")"; - return false; - } + size_t expected_length = qlz_size_decompressed((char*) packet->data().data_ptr()); + if(expected_length > this->max_packet_size){ //Max 16MB. (97% Compression!) + error = "Invalid packet size. (Calculated target length of " + to_string(expected_length) + ". Max length: " + to_string(this->max_packet_size) + ")"; + return false; + } - auto header_length = packet->header().length() + packet->mac().length(); - auto buffer = buffer::allocate_buffer(expected_length + header_length); - size_t data_length = qlz_decompress((char*) packet->data().data_ptr(), &buffer[header_length], &state_decompress); - if(data_length <= 0){ - error = "Could not decompress packet."; - return false; - } + auto header_length = packet->header().length() + packet->mac().length(); + auto buffer = buffer::allocate_buffer(expected_length + header_length); + size_t data_length = qlz_decompress((char*) packet->data().data_ptr(), &buffer[header_length], &state_decompress); + if(data_length <= 0){ + error = "Could not decompress packet."; + return false; + } - memcpy(buffer.data_ptr(), packet->buffer().data_ptr(), header_length); - packet->buffer(buffer.range(0, data_length + header_length)); - return true; + memcpy(buffer.data_ptr(), packet->buffer().data_ptr(), header_length); + packet->buffer(buffer.range(0, data_length + header_length)); + return true; } bool CompressionHandler::progressPacketIn(protocol::BasicPacket* packet, std::string &error) { - if(packet->isCompressed()) { - if(!this->decompress(packet, error)) return false; - packet->setCompressed(false); - } - return true; + if(packet->isCompressed()) { + if(!this->decompress(packet, error)) return false; + packet->setCompressed(false); + } + return true; } bool CompressionHandler::progressPacketOut(protocol::BasicPacket* packet, std::string& error) { - if(packet->has_flag(protocol::PacketFlag::Compressed) && !packet->isCompressed()) { - if(!this->compress(packet, error)) return false; - packet->setCompressed(true); - } - return true; + if(packet->has_flag(protocol::PacketFlag::Compressed) && !packet->isCompressed()) { + if(!this->compress(packet, error)) return false; + packet->setCompressed(true); + } + return true; } CompressionHandler::CompressionHandler() { } diff --git a/src/protocol/CompressionHandler.h b/src/protocol/CompressionHandler.h index a753543..cae4328 100644 --- a/src/protocol/CompressionHandler.h +++ b/src/protocol/CompressionHandler.h @@ -3,19 +3,19 @@ #include "Packet.h" namespace ts { - namespace connection { - class CompressionHandler { - public: - CompressionHandler(); - virtual ~CompressionHandler(); + namespace connection { + class CompressionHandler { + public: + CompressionHandler(); + virtual ~CompressionHandler(); - bool progressPacketOut(protocol::BasicPacket*, std::string&); - bool progressPacketIn(protocol::BasicPacket*, std::string&); + bool progressPacketOut(protocol::BasicPacket*, std::string&); + bool progressPacketIn(protocol::BasicPacket*, std::string&); - size_t max_packet_size = 16 * 1024; - private: - bool compress(protocol::BasicPacket*, std::string &error); - bool decompress(protocol::BasicPacket*, std::string &error); - }; - } + size_t max_packet_size = 16 * 1024; + private: + bool compress(protocol::BasicPacket*, std::string &error); + bool decompress(protocol::BasicPacket*, std::string &error); + }; + } } \ No newline at end of file diff --git a/src/protocol/CryptionHandler.cpp b/src/protocol/CryptionHandler.cpp index aec5063..5941a9d 100644 --- a/src/protocol/CryptionHandler.cpp +++ b/src/protocol/CryptionHandler.cpp @@ -18,364 +18,364 @@ using namespace ts::protocol; CryptionHandler::CryptionHandler() { - memtrack::allocated(this); + memtrack::allocated(this); } CryptionHandler::~CryptionHandler() { - memtrack::freed(this); + memtrack::freed(this); } void CryptionHandler::reset() { - this->useDefaultChipherKeyNonce = true; - this->iv_struct_length = 0; - memset(this->iv_struct, 0, sizeof(this->iv_struct)); - memcpy(this->current_mac, CryptionHandler::default_mac, sizeof(CryptionHandler::default_mac)); + this->useDefaultChipherKeyNonce = true; + this->iv_struct_length = 0; + memset(this->iv_struct, 0, sizeof(this->iv_struct)); + memcpy(this->current_mac, CryptionHandler::default_mac, sizeof(CryptionHandler::default_mac)); - for(auto& cache : this->cache_key_client) - cache.generation = 0xFFEF; - for(auto& cache : this->cache_key_server) - cache.generation = 0xFFEF; + for(auto& cache : this->cache_key_client) + cache.generation = 0xFFEF; + for(auto& cache : this->cache_key_server) + cache.generation = 0xFFEF; } #define SHARED_KEY_BUFFER_LENGTH (256) bool CryptionHandler::setupSharedSecret(const std::string& alpha, const std::string& beta, ecc_key *publicKey, ecc_key *ownKey, std::string &error) { - size_t buffer_length = SHARED_KEY_BUFFER_LENGTH; - uint8_t buffer[SHARED_KEY_BUFFER_LENGTH]; - int err; - if((err = ecc_shared_secret(ownKey, publicKey, buffer, (unsigned long*) &buffer_length)) != CRYPT_OK){ - error = "Could not calculate shared secret. Message: " + string(error_to_string(err)); - return false; - } + size_t buffer_length = SHARED_KEY_BUFFER_LENGTH; + uint8_t buffer[SHARED_KEY_BUFFER_LENGTH]; + int err; + if((err = ecc_shared_secret(ownKey, publicKey, buffer, (unsigned long*) &buffer_length)) != CRYPT_OK){ + error = "Could not calculate shared secret. Message: " + string(error_to_string(err)); + return false; + } - auto result = this->setupSharedSecret(alpha, beta, string((const char*) buffer, buffer_length), error); - return result; + auto result = this->setupSharedSecret(alpha, beta, string((const char*) buffer, buffer_length), error); + return result; } bool CryptionHandler::setupSharedSecret(const std::string& alpha, const std::string& beta, const std::string& sharedKey, std::string &error) { - auto secret_hash = digest::sha1(sharedKey); - assert(secret_hash.length() == SHA_DIGEST_LENGTH); + auto secret_hash = digest::sha1(sharedKey); + assert(secret_hash.length() == SHA_DIGEST_LENGTH); - uint8_t iv_buffer[SHA_DIGEST_LENGTH]; - memcpy(iv_buffer, alpha.data(), 10); - memcpy(&iv_buffer[10], beta.data(), 10); + uint8_t iv_buffer[SHA_DIGEST_LENGTH]; + memcpy(iv_buffer, alpha.data(), 10); + memcpy(&iv_buffer[10], beta.data(), 10); - for (int index = 0; index < SHA_DIGEST_LENGTH; index++) { - iv_buffer[index] ^= (uint8_t) secret_hash[index]; - } + for (int index = 0; index < SHA_DIGEST_LENGTH; index++) { + iv_buffer[index] ^= (uint8_t) secret_hash[index]; + } - { - lock_guard lock(this->cache_key_lock); - memcpy(this->iv_struct, iv_buffer, SHA_DIGEST_LENGTH); - this->iv_struct_length = SHA_DIGEST_LENGTH; + { + lock_guard lock(this->cache_key_lock); + memcpy(this->iv_struct, iv_buffer, SHA_DIGEST_LENGTH); + this->iv_struct_length = SHA_DIGEST_LENGTH; - uint8_t mac_buffer[SHA_DIGEST_LENGTH]; - digest::sha1((const char*) iv_buffer, SHA_DIGEST_LENGTH, mac_buffer); - memcpy(this->current_mac, mac_buffer, 8); + uint8_t mac_buffer[SHA_DIGEST_LENGTH]; + digest::sha1((const char*) iv_buffer, SHA_DIGEST_LENGTH, mac_buffer); + memcpy(this->current_mac, mac_buffer, 8); - this->useDefaultChipherKeyNonce = false; - } + this->useDefaultChipherKeyNonce = false; + } - return true; + return true; } void _fe_neg(fe h, const fe f) { - int32_t f0 = f[0]; - int32_t f1 = f[1]; - int32_t f2 = f[2]; - int32_t f3 = f[3]; - int32_t f4 = f[4]; - int32_t f5 = f[5]; - int32_t f6 = f[6]; - int32_t f7 = f[7]; - int32_t f8 = f[8]; - int32_t f9 = f[9]; - int32_t h0 = -f0; - int32_t h1 = -f1; - int32_t h2 = -f2; - int32_t h3 = -f3; - int32_t h4 = -f4; - int32_t h5 = -f5; - int32_t h6 = -f6; - int32_t h7 = -f7; - int32_t h8 = -f8; - int32_t h9 = -f9; + int32_t f0 = f[0]; + int32_t f1 = f[1]; + int32_t f2 = f[2]; + int32_t f3 = f[3]; + int32_t f4 = f[4]; + int32_t f5 = f[5]; + int32_t f6 = f[6]; + int32_t f7 = f[7]; + int32_t f8 = f[8]; + int32_t f9 = f[9]; + int32_t h0 = -f0; + int32_t h1 = -f1; + int32_t h2 = -f2; + int32_t h3 = -f3; + int32_t h4 = -f4; + int32_t h5 = -f5; + int32_t h6 = -f6; + int32_t h7 = -f7; + int32_t h8 = -f8; + int32_t h9 = -f9; - h[0] = h0; - h[1] = h1; - h[2] = h2; - h[3] = h3; - h[4] = h4; - h[5] = h5; - h[6] = h6; - h[7] = h7; - h[8] = h8; - h[9] = h9; + h[0] = h0; + h[1] = h1; + h[2] = h2; + h[3] = h3; + h[4] = h4; + h[5] = h5; + h[6] = h6; + h[7] = h7; + h[8] = h8; + h[9] = h9; } inline void keyMul(uint8_t(& target_buffer)[32], const uint8_t* publicKey /* compressed */, const uint8_t* privateKey /* uncompressed */, bool negate){ - ge_p3 keyA{}; - ge_p2 result{}; + ge_p3 keyA{}; + ge_p2 result{}; - ge_frombytes_negate_vartime(&keyA, publicKey); - if(negate) { - _fe_neg(*(fe*) &keyA.X, *(const fe*) &keyA.X); /* undo negate */ - _fe_neg(*(fe*) &keyA.T, *(const fe*) &keyA.T); /* undo negate */ - } - ge_scalarmult_vartime(&result, privateKey, &keyA); + ge_frombytes_negate_vartime(&keyA, publicKey); + if(negate) { + _fe_neg(*(fe*) &keyA.X, *(const fe*) &keyA.X); /* undo negate */ + _fe_neg(*(fe*) &keyA.T, *(const fe*) &keyA.T); /* undo negate */ + } + ge_scalarmult_vartime(&result, privateKey, &keyA); - ge_tobytes(target_buffer, &result); + ge_tobytes(target_buffer, &result); } bool CryptionHandler::setupSharedSecretNew(const std::string &alpha, const std::string &beta, const char* privateKey /* uncompressed */, const char* publicKey /* compressed */) { - if(alpha.length() != 10 || beta.length() != 54) - return false; + if(alpha.length() != 10 || beta.length() != 54) + return false; - uint8_t shared[32]; - uint8_t shared_iv[64]; + uint8_t shared[32]; + uint8_t shared_iv[64]; - ed25519_key_exchange(shared, (uint8_t*) publicKey, (uint8_t*) privateKey); - keyMul(shared, reinterpret_cast(publicKey), reinterpret_cast(privateKey), true); //Remote key get negated - digest::sha512((char*) shared, 32, shared_iv); + ed25519_key_exchange(shared, (uint8_t*) publicKey, (uint8_t*) privateKey); + keyMul(shared, reinterpret_cast(publicKey), reinterpret_cast(privateKey), true); //Remote key get negated + digest::sha512((char*) shared, 32, shared_iv); - auto xor_key = alpha + beta; - for(int i = 0; i < 64; i++) - shared_iv[i] ^= (uint8_t) xor_key[i]; + auto xor_key = alpha + beta; + for(int i = 0; i < 64; i++) + shared_iv[i] ^= (uint8_t) xor_key[i]; - { - lock_guard lock(this->cache_key_lock); - memcpy(this->iv_struct, shared_iv, 64); - this->iv_struct_length = 64; + { + lock_guard lock(this->cache_key_lock); + memcpy(this->iv_struct, shared_iv, 64); + this->iv_struct_length = 64; - uint8_t mac_buffer[SHA_DIGEST_LENGTH]; - digest::sha1((char*) this->iv_struct, 64, mac_buffer); - memcpy(this->current_mac, mac_buffer, 8); - this->useDefaultChipherKeyNonce = false; - } + uint8_t mac_buffer[SHA_DIGEST_LENGTH]; + digest::sha1((char*) this->iv_struct, 64, mac_buffer); + memcpy(this->current_mac, mac_buffer, 8); + this->useDefaultChipherKeyNonce = false; + } - return true; + return true; } bool CryptionHandler::generate_key_nonce(protocol::BasicPacket* packet, bool use_default, uint8_t(& key)[16], uint8_t(& nonce)[16]){ - return this->generate_key_nonce( - dynamic_cast(packet) != nullptr, - packet->type().type(), - packet->packetId(), - packet->generationId(), - use_default, - key, - nonce - ); + return this->generate_key_nonce( + dynamic_cast(packet) != nullptr, + packet->type().type(), + packet->packetId(), + packet->generationId(), + use_default, + key, + nonce + ); } #define GENERATE_BUFFER_LENGTH (128) bool CryptionHandler::generate_key_nonce( - bool to_server, /* its from the client to the server */ - protocol::PacketType type, - uint16_t packet_id, - uint16_t generation, - bool use_default, - uint8_t (& key)[16], - uint8_t (& nonce)[16] + bool to_server, /* its from the client to the server */ + protocol::PacketType type, + uint16_t packet_id, + uint16_t generation, + bool use_default, + uint8_t (& key)[16], + uint8_t (& nonce)[16] ) { - if (this->useDefaultChipherKeyNonce || use_default) { - memcpy(key, CryptionHandler::default_key, 16); - memcpy(nonce, CryptionHandler::default_nonce, 16); - return true; - } + if (this->useDefaultChipherKeyNonce || use_default) { + memcpy(key, CryptionHandler::default_key, 16); + memcpy(nonce, CryptionHandler::default_nonce, 16); + return true; + } - auto& key_cache_array = to_server ? this->cache_key_client : this->cache_key_server; - if(type < 0 || type >= key_cache_array.max_size()) { - logError(0, "Tried to generate a crypt key with invalid type ({})!", type); - return false; - } + auto& key_cache_array = to_server ? this->cache_key_client : this->cache_key_server; + if(type < 0 || type >= key_cache_array.max_size()) { + logError(0, "Tried to generate a crypt key with invalid type ({})!", type); + return false; + } - auto& key_cache = key_cache_array[type]; - if(key_cache.generation != generation) { - const size_t buffer_length = 6 + this->iv_struct_length; - sassert(buffer_length < GENERATE_BUFFER_LENGTH); + auto& key_cache = key_cache_array[type]; + if(key_cache.generation != generation) { + const size_t buffer_length = 6 + this->iv_struct_length; + sassert(buffer_length < GENERATE_BUFFER_LENGTH); - char buffer[GENERATE_BUFFER_LENGTH]; - memset(buffer, 0, buffer_length); + char buffer[GENERATE_BUFFER_LENGTH]; + memset(buffer, 0, buffer_length); - if (to_server) { - buffer[0] = 0x31; - } else { - buffer[0] = 0x30; - } - buffer[1] = (char) (type & 0xF); + if (to_server) { + buffer[0] = 0x31; + } else { + buffer[0] = 0x30; + } + buffer[1] = (char) (type & 0xF); - le2be32(generation, buffer, 2); - memcpy(&buffer[6], this->iv_struct, this->iv_struct_length); - digest::sha256(buffer, buffer_length, key_cache.key_nonce); + le2be32(generation, buffer, 2); + memcpy(&buffer[6], this->iv_struct, this->iv_struct_length); + digest::sha256(buffer, buffer_length, key_cache.key_nonce); - key_cache.generation = generation; - } + key_cache.generation = generation; + } - memcpy(key, key_cache.key, 16); - memcpy(nonce, key_cache.nonce, 16); + memcpy(key, key_cache.key, 16); + memcpy(nonce, key_cache.nonce, 16); - //Xor the key - key[0] ^= (uint8_t) ((packet_id >> 8) & 0xFF); - key[1] ^=(packet_id & 0xFF); + //Xor the key + key[0] ^= (uint8_t) ((packet_id >> 8) & 0xFF); + key[1] ^=(packet_id & 0xFF); - return true; + return true; } bool CryptionHandler::verify_encryption(const pipes::buffer_view &packet, uint16_t packet_id, uint16_t generation) { - int err; - int success = false; + int err; + int success = false; - uint8_t key[16], nonce[16]; - if(!generate_key_nonce(true, (protocol::PacketType) (packet[12] & 0xF), packet_id, generation, false, key, nonce)) - return false; + uint8_t key[16], nonce[16]; + if(!generate_key_nonce(true, (protocol::PacketType) (packet[12] & 0xF), packet_id, generation, false, key, nonce)) + return false; - auto mac = packet.view(0, 8); - auto header = packet.view(8, 5); - auto data = packet.view(13); + auto mac = packet.view(0, 8); + auto header = packet.view(8, 5); + auto data = packet.view(13); - auto length = data.length(); + auto length = data.length(); - /* static shareable void buffer */ - const static unsigned long void_target_length = 2048; - static uint8_t void_target_buffer[2048]; - if(void_target_length < length) - return false; + /* static shareable void buffer */ + const static unsigned long void_target_length = 2048; + static uint8_t void_target_buffer[2048]; + if(void_target_length < length) + return false; - err = eax_decrypt_verify_memory(find_cipher("rijndael"), - (uint8_t *) key, /* the key */ - (size_t) 16, /* key is 16 bytes */ - (uint8_t *) nonce, /* the nonce */ - (size_t) 16, /* nonce is 16 bytes */ - (uint8_t *) header.data_ptr(), /* example header */ - (unsigned long) header.length(), /* header length */ - (const unsigned char *) data.data_ptr(), - (unsigned long) data.length(), - (unsigned char *) void_target_buffer, - (unsigned char *) mac.data_ptr(), - (unsigned long) mac.length(), - &success - ); + err = eax_decrypt_verify_memory(find_cipher("rijndael"), + (uint8_t *) key, /* the key */ + (size_t) 16, /* key is 16 bytes */ + (uint8_t *) nonce, /* the nonce */ + (size_t) 16, /* nonce is 16 bytes */ + (uint8_t *) header.data_ptr(), /* example header */ + (unsigned long) header.length(), /* header length */ + (const unsigned char *) data.data_ptr(), + (unsigned long) data.length(), + (unsigned char *) void_target_buffer, + (unsigned char *) mac.data_ptr(), + (unsigned long) mac.length(), + &success + ); - return err == CRYPT_OK && success; + return err == CRYPT_OK && success; } bool CryptionHandler::decryptPacket(protocol::BasicPacket *packet, std::string &error, bool use_default) { - int err; - int success = false; + int err; + int success = false; - auto header = packet->header(); - auto data = packet->data(); + auto header = packet->header(); + auto data = packet->data(); - uint8_t key[16], nonce[16]; - if(!generate_key_nonce(packet, use_default, key, nonce)) { - error = "Could not generate key/nonce"; - return false; - } + uint8_t key[16], nonce[16]; + if(!generate_key_nonce(packet, use_default, key, nonce)) { + error = "Could not generate key/nonce"; + return false; + } - size_t target_length = 2048; - uint8_t target_buffer[2048]; - auto length = data.length(); - if(target_length < length) { - error = "buffer too large"; - return false; - } + size_t target_length = 2048; + uint8_t target_buffer[2048]; + auto length = data.length(); + if(target_length < length) { + error = "buffer too large"; + return false; + } - err = eax_decrypt_verify_memory(find_cipher("rijndael"), - (uint8_t *) key, /* the key */ - (unsigned long) 16, /* key is 16 bytes */ - (uint8_t *) nonce, /* the nonce */ - (unsigned long) 16, /* nonce is 16 bytes */ - (uint8_t *) header.data_ptr(), /* example header */ - (unsigned long) header.length(), /* header length */ - (const unsigned char *) data.data_ptr(), - (unsigned long) data.length(), - (unsigned char *) target_buffer, - (unsigned char *) packet->mac().data_ptr(), - (unsigned long) packet->mac().length(), - &success - ); + err = eax_decrypt_verify_memory(find_cipher("rijndael"), + (uint8_t *) key, /* the key */ + (unsigned long) 16, /* key is 16 bytes */ + (uint8_t *) nonce, /* the nonce */ + (unsigned long) 16, /* nonce is 16 bytes */ + (uint8_t *) header.data_ptr(), /* example header */ + (unsigned long) header.length(), /* header length */ + (const unsigned char *) data.data_ptr(), + (unsigned long) data.length(), + (unsigned char *) target_buffer, + (unsigned char *) packet->mac().data_ptr(), + (unsigned long) packet->mac().length(), + &success + ); - if((err) != CRYPT_OK){ - error = "eax_decrypt_verify_memory(...) returned " + to_string(err) + "/" + error_to_string(err); - return false; - } - if(!success){ - error = "memory verify failed!"; - return false; - } + if((err) != CRYPT_OK){ + error = "eax_decrypt_verify_memory(...) returned " + to_string(err) + "/" + error_to_string(err); + return false; + } + if(!success){ + error = "memory verify failed!"; + return false; + } - packet->data(pipes::buffer_view{target_buffer, length}); - packet->setEncrypted(false); - return true; + packet->data(pipes::buffer_view{target_buffer, length}); + packet->setEncrypted(false); + return true; } bool CryptionHandler::encryptPacket(protocol::BasicPacket *packet, std::string &error, bool use_default) { - uint8_t key[16], nonce[16]; - if(!generate_key_nonce(packet, use_default, key, nonce)) { - error = "Could not generate key/nonce"; - return false; - } + uint8_t key[16], nonce[16]; + if(!generate_key_nonce(packet, use_default, key, nonce)) { + error = "Could not generate key/nonce"; + return false; + } - size_t length = packet->data().length(); + size_t length = packet->data().length(); - size_t tag_length = 8; - char tag_buffer[8]; + size_t tag_length = 8; + char tag_buffer[8]; - size_t target_length = 2048; - uint8_t target_buffer[2048]; - if(target_length < length) { - error = "buffer too large"; - return false; - } + size_t target_length = 2048; + uint8_t target_buffer[2048]; + if(target_length < length) { + error = "buffer too large"; + return false; + } - int err; - if((err = eax_encrypt_authenticate_memory(find_cipher("rijndael"), - (uint8_t *) key, /* the key */ - (unsigned long) 16, /* key is 16 bytes */ - (uint8_t *) nonce, /* the nonce */ - (unsigned long) 16, /* nonce is 16 bytes */ - (uint8_t *) packet->header().data_ptr(), /* example header */ - (unsigned long) packet->header().length(), /* header length */ - (uint8_t *) packet->data().data_ptr(), /* The plain text */ - (unsigned long) packet->data().length(), /* Plain text length */ - (uint8_t *) target_buffer, /* The result buffer */ - (uint8_t *) tag_buffer, - (unsigned long *) &tag_length - )) != CRYPT_OK){ - error = "eax_encrypt_authenticate_memory(...) returned " + to_string(err) + "/" + error_to_string(err); - return false; - } - assert(tag_length == 8); + int err; + if((err = eax_encrypt_authenticate_memory(find_cipher("rijndael"), + (uint8_t *) key, /* the key */ + (unsigned long) 16, /* key is 16 bytes */ + (uint8_t *) nonce, /* the nonce */ + (unsigned long) 16, /* nonce is 16 bytes */ + (uint8_t *) packet->header().data_ptr(), /* example header */ + (unsigned long) packet->header().length(), /* header length */ + (uint8_t *) packet->data().data_ptr(), /* The plain text */ + (unsigned long) packet->data().length(), /* Plain text length */ + (uint8_t *) target_buffer, /* The result buffer */ + (uint8_t *) tag_buffer, + (unsigned long *) &tag_length + )) != CRYPT_OK){ + error = "eax_encrypt_authenticate_memory(...) returned " + to_string(err) + "/" + error_to_string(err); + return false; + } + assert(tag_length == 8); - packet->data(pipes::buffer_view{target_buffer, length}); - packet->mac().write(tag_buffer, tag_length); - packet->setEncrypted(true); - return true; + packet->data(pipes::buffer_view{target_buffer, length}); + packet->mac().write(tag_buffer, tag_length); + packet->setEncrypted(true); + return true; } bool CryptionHandler::progressPacketIn(protocol::BasicPacket* packet, std::string& error, bool use_default) { - while(blocked) - this_thread::yield(); + while(blocked) + this_thread::yield(); - if(packet->isEncrypted()){ - bool success = decryptPacket(packet, error, use_default); - if(success) packet->setEncrypted(false); - return success; - } - return true; + if(packet->isEncrypted()){ + bool success = decryptPacket(packet, error, use_default); + if(success) packet->setEncrypted(false); + return success; + } + return true; } bool CryptionHandler::progressPacketOut(protocol::BasicPacket* packet, std::string& error, bool use_default) { - while(blocked) - this_thread::yield(); + while(blocked) + this_thread::yield(); - if(packet->has_flag(PacketFlag::Unencrypted)) { - packet->mac().write(this->current_mac, 8); - } else { - bool success = encryptPacket(packet, error, use_default); - if(success) packet->setEncrypted(true); - return success; - } - return true; + if(packet->has_flag(PacketFlag::Unencrypted)) { + packet->mac().write(this->current_mac, 8); + } else { + bool success = encryptPacket(packet, error, use_default); + if(success) packet->setEncrypted(true); + return success; + } + return true; } diff --git a/src/protocol/CryptionHandler.h b/src/protocol/CryptionHandler.h index 51c8fa7..54638b7 100644 --- a/src/protocol/CryptionHandler.h +++ b/src/protocol/CryptionHandler.h @@ -10,18 +10,18 @@ namespace ts { namespace connection { class CryptionHandler { enum Methode { - TEAMSPEAK_3_1, - TEAMSPEAK_3 + TEAMSPEAK_3_1, + TEAMSPEAK_3 }; struct KeyCache { - uint16_t generation = 0xFFEF; - union { - struct { + uint16_t generation = 0xFFEF; + union { + struct { uint8_t key[16]; uint8_t nonce[16]; - }; + }; uint8_t key_nonce[32]; - }; + }; }; public: CryptionHandler(); @@ -29,12 +29,12 @@ namespace ts { void reset(); - //TeamSpeak old - bool setupSharedSecret(const std::string& alpha, const std::string& beta, ecc_key* publicKey, ecc_key* ownKey, std::string &error); + //TeamSpeak old + bool setupSharedSecret(const std::string& alpha, const std::string& beta, ecc_key* publicKey, ecc_key* ownKey, std::string &error); bool setupSharedSecret(const std::string& alpha, const std::string& beta, const std::string& sharedKey, std::string &error); - //TeamSpeak new - bool setupSharedSecretNew(const std::string& alpha, const std::string& beta, const char privateKey[32], const char publicKey[32]); + //TeamSpeak new + bool setupSharedSecretNew(const std::string& alpha, const std::string& beta, const char privateKey[32], const char publicKey[32]); bool progressPacketOut(protocol::BasicPacket*, std::string&, bool use_default); bool progressPacketIn(protocol::BasicPacket*, std::string&, bool use_default); @@ -47,7 +47,7 @@ namespace ts { bool use_default() { return this->useDefaultChipherKeyNonce; } private: - static constexpr char default_key[16] = {'c', ':', '\\', 'w', 'i', 'n', 'd', 'o', 'w', 's', '\\', 's', 'y', 's', 't', 'e'}; //c:\windows\syste + static constexpr char default_key[16] = {'c', ':', '\\', 'w', 'i', 'n', 'd', 'o', 'w', 's', '\\', 's', 'y', 's', 't', 'e'}; //c:\windows\syste static constexpr char default_nonce[16] = {'m', '\\', 'f', 'i', 'r', 'e', 'w', 'a', 'l', 'l', '3', '2', '.', 'c', 'p', 'l'}; //m\firewall32.cpl static constexpr char default_mac[8] = {'T', 'S', '3', 'I', 'N', 'I', 'T', '1'}; //TS3INIT1 @@ -55,26 +55,26 @@ namespace ts { bool decryptPacket(protocol::BasicPacket *, std::string &, bool use_default); bool encryptPacket(protocol::BasicPacket *, std::string &, bool use_default); - bool generate_key_nonce(bool /* to server */, protocol::PacketType /* type */, uint16_t /* packet id */, uint16_t /* generation */, bool /* use default */, uint8_t(&)[16] /* key */, uint8_t(&)[16] /* nonce */); + bool generate_key_nonce(bool /* to server */, protocol::PacketType /* type */, uint16_t /* packet id */, uint16_t /* generation */, bool /* use default */, uint8_t(&)[16] /* key */, uint8_t(&)[16] /* nonce */); bool generate_key_nonce(protocol::BasicPacket* packet, bool use_default, uint8_t(&)[16] /* key */, uint8_t(&)[16] /* nonce */); //The default key and nonce bool useDefaultChipherKeyNonce = true; - bool blocked = false; + bool blocked = false; /* for the old protocol SHA1 length for the new 64 bytes */ uint8_t iv_struct[64]; uint8_t iv_struct_length = 0; - uint8_t current_mac[8]; + uint8_t current_mac[8]; - std::mutex cache_key_lock; - std::array cache_key_client; - std::array cache_key_server; + std::mutex cache_key_lock; + std::array cache_key_client; + std::array cache_key_server; - static_assert(sizeof(current_mac) == sizeof(default_mac), "invalid mac"); - static_assert(sizeof(iv_struct) == 64, "invalid iv struct"); + static_assert(sizeof(current_mac) == sizeof(default_mac), "invalid mac"); + static_assert(sizeof(iv_struct) == 64, "invalid iv struct"); }; } } \ No newline at end of file diff --git a/src/protocol/Packet.cpp b/src/protocol/Packet.cpp index b2b0714..bf9e8aa 100644 --- a/src/protocol/Packet.cpp +++ b/src/protocol/Packet.cpp @@ -21,9 +21,9 @@ namespace ts { types.insert({type, *this}); } - PacketTypeInfo::~PacketTypeInfo() { - if(this->owns_data) - delete this->data; + PacketTypeInfo::~PacketTypeInfo() { + if(this->owns_data) + delete this->data; } PacketTypeInfo::PacketTypeInfo(const PacketTypeInfo &red) : data(red.data) { } @@ -82,7 +82,7 @@ namespace ts { new_buffer.write(this->_buffer, index); for(const auto& buffer : data) { - new_buffer.write(buffer, buffer.length(), index); + new_buffer.write(buffer, buffer.length(), index); index += buffer.length(); } @@ -119,10 +119,10 @@ namespace ts { * @return */ std::unique_ptr ServerPacket::from_buffer(const pipes::buffer_view &buffer) { - auto result = make_unique(); + auto result = make_unique(); - result->_buffer = buffer.own_buffer(); - result->_header_length = SERVER_HEADER_SIZE; + result->_buffer = buffer.own_buffer(); + result->_header_length = SERVER_HEADER_SIZE; return result; } @@ -161,13 +161,13 @@ namespace ts { } - std::unique_ptr ClientPacket::from_buffer(const pipes::buffer_view &buffer) { - auto result = make_unique(); + std::unique_ptr ClientPacket::from_buffer(const pipes::buffer_view &buffer) { + auto result = make_unique(); - result->_buffer = buffer.own_buffer(); - result->_header_length = CLIENT_HEADER_SIZE; + result->_buffer = buffer.own_buffer(); + 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()) { diff --git a/src/protocol/Packet.h b/src/protocol/Packet.h index 3c388be..d95f28f 100644 --- a/src/protocol/Packet.h +++ b/src/protocol/Packet.h @@ -10,25 +10,25 @@ namespace ts { namespace protocol { - enum PacketType : uint8_t { - VOICE = 0x00, - VOICE_WHISPER = 0x01, - COMMAND = 0x02, - COMMAND_LOW = 0x03, - PING = 0x04, - PONG = 0x05, - ACK = 0x06, - ACK_LOW = 0x07, - INIT1 = 0x08, + enum PacketType : uint8_t { + VOICE = 0x00, + VOICE_WHISPER = 0x01, + COMMAND = 0x02, + COMMAND_LOW = 0x03, + PING = 0x04, + PONG = 0x05, + ACK = 0x06, + ACK_LOW = 0x07, + INIT1 = 0x08, - PACKET_MAX = INIT1, - UNDEFINED = 0xFF - }; + PACKET_MAX = INIT1, + UNDEFINED = 0xFF + }; struct PacketTypeProperties { std::string name; - PacketType type; - int max_length; + PacketType type; + int max_length; bool requireAcknowledge; }; @@ -48,7 +48,7 @@ namespace ts { static PacketTypeInfo fromid(int id); std::string name() const { return data->name; } - PacketType type() const { return data->type; } + PacketType type() const { return data->type; } bool requireAcknowledge(){ return data->requireAcknowledge; } @@ -60,19 +60,19 @@ namespace ts { return other.data->type != this->data->type; } - int max_length() const { return data->max_length; } - inline bool fragmentable() { return *this == PacketTypeInfo::Command || *this == PacketTypeInfo::CommandLow; } - inline bool compressable() { return *this == PacketTypeInfo::Command || *this == PacketTypeInfo::CommandLow; } + int max_length() const { return data->max_length; } + inline bool fragmentable() { return *this == PacketTypeInfo::Command || *this == PacketTypeInfo::CommandLow; } + inline bool compressable() { return *this == PacketTypeInfo::Command || *this == PacketTypeInfo::CommandLow; } PacketTypeInfo(const PacketTypeInfo&); - PacketTypeInfo(PacketTypeInfo&& remote) : data(remote.data) {} + PacketTypeInfo(PacketTypeInfo&& remote) : data(remote.data) {} - ~PacketTypeInfo(); + ~PacketTypeInfo(); private: static std::map types; PacketTypeInfo(const std::string&, PacketType, bool, int) noexcept; - PacketTypeProperties* data; - bool owns_data = false; + PacketTypeProperties* data; + bool owns_data = false; }; struct PacketIdManagerData { @@ -101,8 +101,8 @@ namespace ts { return static_cast((data->packetCounter[type.type()] >> 16) & 0xFFFF); } - void reset() { - memset(&data->packetCounter[0], 0, sizeof(uint32_t) * 16); + void reset() { + memset(&data->packetCounter[0], 0, sizeof(uint32_t) * 16); } private: std::shared_ptr data; @@ -116,7 +116,7 @@ namespace ts { Compressed = 0x40, //If packet type voice than its the header Unencrypted = 0x80 }; - typedef uint8_t PacketFlags; + typedef uint8_t PacketFlags; std::string to_string(PacketFlag flag); } @@ -130,8 +130,8 @@ namespace ts { explicit BasicPacket(size_t header_length, size_t data_length); virtual ~BasicPacket(); - BasicPacket(const BasicPacket&) = delete; - BasicPacket(BasicPacket&&) = delete; + BasicPacket(const BasicPacket&) = delete; + BasicPacket(BasicPacket&&) = delete; virtual uint16_t packetId() const = 0; virtual uint16_t generationId() const = 0; @@ -139,190 +139,190 @@ namespace ts { /* packet flag info */ 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; /* manipulate flags */ inline void set_flags(PacketFlag::PacketFlags flags) { - uint8_t& byte = this->_flags_type_byte(); - byte &= 0xF; /* clear all flags */ - byte |= (flags & 0xF0); + uint8_t& byte = this->_flags_type_byte(); + byte &= 0xF; /* clear all flags */ + byte |= (flags & 0xF0); } inline void enable_flag(PacketFlag::PacketFlag flag){ this->toggle_flag(flag, true); } - inline void toggle_flag(PacketFlag::PacketFlag flag, bool state) { - if(state) - this->_flags_type_byte() |= flag; - else - this->_flags_type_byte() &= (uint8_t) ~flag; + inline void toggle_flag(PacketFlag::PacketFlag flag, bool state) { + if(state) + this->_flags_type_byte() |= flag; + else + this->_flags_type_byte() &= (uint8_t) ~flag; } virtual void applyPacketId(PacketIdManager &); virtual void applyPacketId(uint16_t, uint16_t); - void setListener(std::unique_ptr> listener){ - if(!this->type().requireAcknowledge()) - throw std::logic_error("Packet type does not support a acknowledge listener!"); - this->listener = std::move(listener); - } - inline std::unique_ptr>& getListener() { return this->listener; } + void setListener(std::unique_ptr> listener){ + if(!this->type().requireAcknowledge()) + throw std::logic_error("Packet type does not support a acknowledge listener!"); + this->listener = std::move(listener); + } + inline std::unique_ptr>& getListener() { return this->listener; } - inline size_t length() const { return this->_buffer.length(); } - 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 size_t mac_length() const { return MAC_SIZE; } + inline size_t length() const { return this->_buffer.length(); } + 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 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 pipes::buffer header() { return this->_buffer.range(MAC_SIZE, this->_header_length); } - inline size_t header_length() const { return 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 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 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 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 pipes::buffer data() { return this->_buffer.range(MAC_SIZE + this->_header_length); } - void append_data(const std::vector &data); + void append_data(const std::vector &data); - inline void data(const pipes::buffer_view &data){ - 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()); + inline void data(const pipes::buffer_view &data){ + 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()); } - inline void mac(const pipes::buffer_view &_new){ + inline void mac(const pipes::buffer_view &_new){ assert(_new.length() >= MAC_SIZE); memcpy(this->_buffer.data_ptr(), _new.data_ptr(), MAC_SIZE); } - [[nodiscard]] inline bool isEncrypted() const { return this->memory_state.encrypted; } - inline void setEncrypted(bool flag){ this->memory_state.encrypted = flag; } + [[nodiscard]] inline bool isEncrypted() const { return this->memory_state.encrypted; } + inline void setEncrypted(bool flag){ this->memory_state.encrypted = flag; } - [[nodiscard]] inline bool isCompressed() const { return this->memory_state.compressed; } - inline void setCompressed(bool flag){ this->memory_state.compressed = flag; } + [[nodiscard]] inline bool isCompressed() const { return this->memory_state.compressed; } + 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; } Command asCommand(); - //Has the size of a byte - union { + //Has the size of a byte + union { #ifdef WIN32 __pragma(pack(push, 1)) #endif - struct { - bool encrypted: 1; - bool compressed: 1; - bool fragment_entry: 1; + struct { + bool encrypted: 1; + bool compressed: 1; + bool fragment_entry: 1; - bool id_branded: 1; - } + bool id_branded: 1; + } #ifdef WIN32 __pragma(pack(pop)); #else __attribute__((packed)); #endif - uint8_t flags = 0; - } memory_state; + uint8_t flags = 0; + } memory_state; - pipes::buffer buffer() { return this->_buffer; } - void buffer(pipes::buffer buffer) { - assert(buffer.length() >= this->_header_length + MAC_SIZE); - this->_buffer = std::move(buffer); - } + pipes::buffer buffer() { return this->_buffer; } + void buffer(pipes::buffer buffer) { + assert(buffer.length() >= this->_header_length + MAC_SIZE); + this->_buffer = std::move(buffer); + } protected: - BasicPacket() = default; + BasicPacket() = default; - virtual const uint8_t& _flags_type_byte() const = 0; - virtual uint8_t& _flags_type_byte() = 0; + virtual const uint8_t& _flags_type_byte() const = 0; + virtual uint8_t& _flags_type_byte() = 0; - virtual void setPacketId(uint16_t, uint16_t) = 0; - uint8_t _header_length; - pipes::buffer _buffer; + virtual void setPacketId(uint16_t, uint16_t) = 0; + uint8_t _header_length; + pipes::buffer _buffer; uint16_t genId = 0; - std::unique_ptr> listener; + std::unique_ptr> listener; }; - /** - * Packet from the client - */ - class ClientPacket : public BasicPacket { - friend std::unique_ptr std::make_unique(); - public: - static constexpr size_t META_MAC_SIZE = 8; - static constexpr size_t META_HEADER_SIZE = CLIENT_HEADER_SIZE; - static constexpr size_t META_SIZE = META_MAC_SIZE + META_HEADER_SIZE; + /** + * Packet from the client + */ + class ClientPacket : public BasicPacket { + friend std::unique_ptr std::make_unique(); + public: + static constexpr size_t META_MAC_SIZE = 8; + static constexpr size_t META_HEADER_SIZE = CLIENT_HEADER_SIZE; + static constexpr size_t META_SIZE = META_MAC_SIZE + META_HEADER_SIZE; - [[nodiscard]] static std::unique_ptr from_buffer(const pipes::buffer_view& buffer); + [[nodiscard]] static std::unique_ptr from_buffer(const pipes::buffer_view& buffer); - ClientPacket(const PacketTypeInfo& type, const pipes::buffer_view& data); - ClientPacket(const PacketTypeInfo& type, uint8_t flag_mask, const pipes::buffer_view& data); - ~ClientPacket() override; - ClientPacket(const ClientPacket&) = delete; - ClientPacket(ClientPacket&&) = delete; + ClientPacket(const PacketTypeInfo& type, const pipes::buffer_view& data); + ClientPacket(const PacketTypeInfo& type, uint8_t flag_mask, const pipes::buffer_view& data); + ~ClientPacket() override; + ClientPacket(const ClientPacket&) = delete; + ClientPacket(ClientPacket&&) = delete; - uint16_t clientId() const; - void clientId(uint16_t); + uint16_t clientId() const; + void clientId(uint16_t); - uint16_t packetId() const override; + uint16_t packetId() const override; - uint16_t generationId() const override; - void generationId(uint16_t generation) { this->genId = generation; } + uint16_t generationId() const override; + void generationId(uint16_t generation) { this->genId = generation; } - PacketTypeInfo type() const override; - void type(const PacketTypeInfo&); + PacketTypeInfo type() const override; + void type(const PacketTypeInfo&); - private: - ClientPacket() = default; + private: + ClientPacket() = default; - const uint8_t &_flags_type_byte() const override { - return this->header().data_ptr()[4]; - } + const uint8_t &_flags_type_byte() const override { + return this->header().data_ptr()[4]; + } - uint8_t &_flags_type_byte() override { - return this->header().data_ptr()[4]; - } + uint8_t &_flags_type_byte() override { + return this->header().data_ptr()[4]; + } - void setPacketId(uint16_t, uint16_t) override; - }; + void setPacketId(uint16_t, uint16_t) override; + }; /** * Packet from the server */ class ServerPacket : public BasicPacket { - friend std::unique_ptr std::make_unique(); + friend std::unique_ptr std::make_unique(); public: - static constexpr size_t META_MAC_SIZE = 8; - 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_MAC_SIZE = 8; + static constexpr size_t META_HEADER_SIZE = SERVER_HEADER_SIZE; + static constexpr size_t META_SIZE = META_MAC_SIZE + META_HEADER_SIZE; - [[nodiscard]] static std::unique_ptr from_buffer(const pipes::buffer_view& buffer); + [[nodiscard]] static std::unique_ptr from_buffer(const pipes::buffer_view& buffer); ServerPacket(uint8_t flagMask, 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(const ServerPacket&) = delete; - ServerPacket(ServerPacket&&) = delete; + ServerPacket(const ServerPacket&) = delete; + ServerPacket(ServerPacket&&) = delete; [[nodiscard]] uint16_t packetId() const override; - [[nodiscard]] uint16_t generationId() const override; - void generationId(uint16_t generation) { this->genId = generation; } - [[nodiscard]] PacketTypeInfo type() const override; + [[nodiscard]] uint16_t generationId() const override; + void generationId(uint16_t generation) { this->genId = generation; } + [[nodiscard]] PacketTypeInfo type() const override; - private: - ServerPacket() = default; + private: + ServerPacket() = default; - [[nodiscard]] const uint8_t &_flags_type_byte() const override { - return this->header().data_ptr()[2]; - } + [[nodiscard]] const uint8_t &_flags_type_byte() const override { + return this->header().data_ptr()[2]; + } - uint8_t &_flags_type_byte() override { - return this->header().data_ptr()[2]; - } + uint8_t &_flags_type_byte() override { + return this->header().data_ptr()[2]; + } - void setPacketId(uint16_t, uint16_t) override; + void setPacketId(uint16_t, uint16_t) override; }; } } \ No newline at end of file diff --git a/src/protocol/buffers.cpp b/src/protocol/buffers.cpp index ae4fe6e..acadaa0 100644 --- a/src/protocol/buffers.cpp +++ b/src/protocol/buffers.cpp @@ -10,11 +10,11 @@ using namespace ts::buffer; #endif meminfo buffer::buffer_memory() { - size_t bytes_buffer = 0; - size_t bytes_buffer_used = 0; - size_t bytes_internal = 0; - size_t nodes = 0; - size_t nodes_full = 0; + size_t bytes_buffer = 0; + size_t bytes_buffer_used = 0; + size_t bytes_internal = 0; + size_t nodes = 0; + size_t nodes_full = 0; - return {bytes_buffer, bytes_buffer_used, bytes_internal, nodes, nodes_full}; + return {bytes_buffer, bytes_buffer_used, bytes_internal, nodes, nodes_full}; } \ No newline at end of file diff --git a/src/protocol/buffers.h b/src/protocol/buffers.h index 6d6ae9a..82e689e 100644 --- a/src/protocol/buffers.h +++ b/src/protocol/buffers.h @@ -66,7 +66,7 @@ namespace ts { ~SortedBufferQueue() = default; - ts::protocol::PacketTypeInfo type() { return this->_type; } + ts::protocol::PacketTypeInfo type() { return this->_type; } void skipPacket(){ threads::MutexLock lock(this->lock); @@ -96,59 +96,59 @@ namespace ts { return nullptr; } - std::shared_ptr peekNext(uint32_t index) { - threads::MutexLock lock(this->lock); - if(this->ignoreOrder) { - if(this->packets.size() > index) - return this->packets[index]; - else - return nullptr; - } - return this->find_packet(this->current.index + index); - } + std::shared_ptr peekNext(uint32_t index) { + threads::MutexLock lock(this->lock); + if(this->ignoreOrder) { + if(this->packets.size() > index) + return this->packets[index]; + else + return nullptr; + } + return this->find_packet(this->current.index + index); + } - void pop_packets(int32_t count = -1) { - if(count == -1) count = 1; + void pop_packets(int32_t count = -1) { + if(count == -1) count = 1; - threads::MutexLock lock(this->lock); - if(this->ignoreOrder) { - while(count-- > 0 && !this->packets.empty()) this->packets.pop_front(); - return; - } + threads::MutexLock lock(this->lock); + if(this->ignoreOrder) { + while(count-- > 0 && !this->packets.empty()) this->packets.pop_front(); + return; + } - auto until = this->current.index + count; - while(this->current.index < until) { - for(auto it = this->packets.begin(); it != this->packets.end(); it++) { - if((*it)->packetId() == this->current.packet_id) { - this->packets.erase(it); - break; - } - } - this->current.index++; - } - } + auto until = this->current.index + count; + while(this->current.index < until) { + for(auto it = this->packets.begin(); it != this->packets.end(); it++) { + if((*it)->packetId() == this->current.packet_id) { + this->packets.erase(it); + break; + } + } + this->current.index++; + } + } bool push_pack(const std::shared_ptr& pkt){ threads::MutexLock lock(this->lock); if(this->ignoreOrder) { this->packets.push_back(pkt); - if(this->current.packet_id > pkt->packetId()) { - if(this->current.packet_id > 0xFF00 && pkt->packetId() < 0xFF) { - this->current.packet_id = pkt->packetId(); - this->current.generation++; - } - } else this->current.packet_id = pkt->packetId(); + if(this->current.packet_id > pkt->packetId()) { + if(this->current.packet_id > 0xFF00 && pkt->packetId() < 0xFF) { + this->current.packet_id = pkt->packetId(); + this->current.generation++; + } + } else this->current.packet_id = pkt->packetId(); return true; } if(this->current.packet_id > pkt->packetId()) { - if(this->current.packet_id < 0xFF00 || pkt->packetId() > 0xFF) { + if(this->current.packet_id < 0xFF00 || pkt->packetId() > 0xFF) { #ifndef NO_LOG - debugMessage(0, "Invalid packed pushpack! Current index {} (generation {}) Packet index {}", this->current.packet_id, this->current.generation, pkt->packetId()); + debugMessage(0, "Invalid packed pushpack! Current index {} (generation {}) Packet index {}", this->current.packet_id, this->current.generation, pkt->packetId()); #endif - return false; - } + return false; + } } this->packets.push_back(pkt); return true; @@ -158,37 +158,37 @@ namespace ts { this->current.index = 0; } - std::unique_lock try_lock_queue() { - threads::MutexTryLock lock(this->lock); - if(!lock) return {}; - return std::unique_lock(this->lock); - } + std::unique_lock try_lock_queue() { + threads::MutexTryLock lock(this->lock); + if(!lock) return {}; + return std::unique_lock(this->lock); + } - std::unique_lock try_lock_execute() { - threads::MutexTryLock lock(this->execute_lock); - if(!lock) return {}; - return std::unique_lock(this->execute_lock); - } + std::unique_lock try_lock_execute() { + threads::MutexTryLock lock(this->execute_lock); + if(!lock) return {}; + return std::unique_lock(this->execute_lock); + } - uint16_t current_packet_id() { return this->current.packet_id; } - uint16_t current_generation_id() { return this->current.generation; } + uint16_t current_packet_id() { return this->current.packet_id; } + uint16_t current_generation_id() { return this->current.generation; } - uint16_t calculate_generation(uint16_t packetId) { - if(packetId >= this->current.packet_id) return this->current.generation; + uint16_t calculate_generation(uint16_t packetId) { + if(packetId >= this->current.packet_id) return this->current.generation; - if(packetId < 0xFF && this->current.packet_id > 0xFF00) - return this->current.generation + 1; + if(packetId < 0xFF && this->current.packet_id > 0xFF00) + return this->current.generation + 1; - return this->current.generation; - } + return this->current.generation; + } union PacketPair { - uint32_t index; - struct { - uint16_t packet_id; - uint16_t generation; - }; - }; + uint32_t index; + struct { + uint16_t packet_id; + uint16_t generation; + }; + }; PacketPair current{0}; private: @@ -200,27 +200,27 @@ namespace ts { }; struct size { - enum value : uint8_t { - unset, - min, - Bytes_512 = min, - Bytes_1024, - Bytes_1536, - max - }; + enum value : uint8_t { + unset, + min, + Bytes_512 = min, + Bytes_1024, + Bytes_1536, + max + }; - static inline size_t byte_length(value size) { - switch (size) { - case Bytes_512: - return 512; - case Bytes_1024: - return 1024; - case Bytes_1536: - return 1536; - default: - return 0; - } - } + static inline size_t byte_length(value size) { + switch (size) { + case Bytes_512: + return 512; + case Bytes_1024: + return 1024; + case Bytes_1536: + return 1536; + default: + return 0; + } + } }; //typedef std::unique_ptr buffer_t; @@ -228,42 +228,42 @@ namespace ts { extern buffer_t allocate_buffer(size::value /* size */); inline buffer_t allocate_buffer(size_t length) { - pipes::buffer result; - if(length <= 512) - result = allocate_buffer(size::Bytes_512); - else if(length <= 1024) - result = allocate_buffer(size::Bytes_1024); - else if(length <= 1536) - result = allocate_buffer(size::Bytes_1536); - else { - return pipes::buffer{length}; - } - result.resize(length); - return result; + pipes::buffer result; + if(length <= 512) + result = allocate_buffer(size::Bytes_512); + else if(length <= 1024) + result = allocate_buffer(size::Bytes_1024); + else if(length <= 1536) + result = allocate_buffer(size::Bytes_1536); + else { + return pipes::buffer{length}; + } + result.resize(length); + return result; } - struct cleaninfo { - size_t bytes_freed_internal; - size_t bytes_freed_buffer; - }; - struct cleanmode { - enum value { - CHUNKS = 0x01, - BLOCKS = 0x02, + struct cleaninfo { + size_t bytes_freed_internal; + size_t bytes_freed_buffer; + }; + struct cleanmode { + enum value { + CHUNKS = 0x01, + BLOCKS = 0x02, - CHUNKS_BLOCKS = 0x03 - }; - }; - extern cleaninfo cleanup_buffers(cleanmode::value /* mode */); + CHUNKS_BLOCKS = 0x03 + }; + }; + extern cleaninfo cleanup_buffers(cleanmode::value /* mode */); - struct meminfo { - size_t bytes_buffer = 0; - size_t bytes_buffer_used = 0; - size_t bytes_internal = 0; + struct meminfo { + size_t bytes_buffer = 0; + size_t bytes_buffer_used = 0; + size_t bytes_internal = 0; - size_t nodes = 0; - size_t nodes_full = 0; - }; - extern meminfo buffer_memory(); + size_t nodes = 0; + size_t nodes_full = 0; + }; + extern meminfo buffer_memory(); } } \ No newline at end of file diff --git a/src/protocol/buffers_allocator_a.cpp b/src/protocol/buffers_allocator_a.cpp index b2882d6..497ab56 100644 --- a/src/protocol/buffers_allocator_a.cpp +++ b/src/protocol/buffers_allocator_a.cpp @@ -15,38 +15,38 @@ using namespace ts::buffer; #define MEM_BLOCK_MAGIC 0xCDEF class spin_lock { - std::atomic_flag locked = ATOMIC_FLAG_INIT; - public: - void lock() { - uint8_t round = 0; - while (locked.test_and_set(std::memory_order_acquire)) { - //Yield when we're using this lock for a longer time, which we usually not doing - if(round++ % 8 == 0) - std::this_thread::yield(); - } - } + std::atomic_flag locked = ATOMIC_FLAG_INIT; + public: + void lock() { + uint8_t round = 0; + while (locked.test_and_set(std::memory_order_acquire)) { + //Yield when we're using this lock for a longer time, which we usually not doing + if(round++ % 8 == 0) + std::this_thread::yield(); + } + } - inline bool try_lock() { - return !locked.test_and_set(std::memory_order_acquire); - } + inline bool try_lock() { + return !locked.test_and_set(std::memory_order_acquire); + } - void unlock() { - locked.clear(std::memory_order_release); - } + void unlock() { + locked.clear(std::memory_order_release); + } }; typedef spin_lock fast_lock_t; #pragma pack(push, 1) struct buffer_entry_head { #ifdef MEM_BUFFER_MAGIC - uint16_t magic; + uint16_t magic; #endif - uint32_t base_offset : 24; - uint8_t base_index : 8; + uint32_t base_offset : 24; + uint8_t base_index : 8; }; struct buffer_entry : buffer_entry_head { - char buffer[0]; + char buffer[0]; }; struct block_chain; @@ -54,339 +54,339 @@ struct block_chain; /* 32 buffers/block */ struct buffer_block { #ifdef MEM_BLOCK_MAGIC - uint16_t magic; + uint16_t magic; #endif - uint8_t block_index; /* block index within the chain */ - block_chain* chain_entry; - fast_lock_t block_lock{}; - size::value type = size::unset; - union { - uint32_t flag_free = 0; - uint8_t flag_used8[4]; - }; + uint8_t block_index; /* block index within the chain */ + block_chain* chain_entry; + fast_lock_t block_lock{}; + size::value type = size::unset; + union { + uint32_t flag_free = 0; + uint8_t flag_used8[4]; + }; - buffer_entry buffers[0]; + buffer_entry buffers[0]; }; #pragma pack(pop) struct block_chain { - uint8_t type_index[buffer::size::max - buffer::size::min]; - block_chain* previous = nullptr; - block_chain* next = nullptr; + uint8_t type_index[buffer::size::max - buffer::size::min]; + block_chain* previous = nullptr; + block_chain* next = nullptr; - uint8_t block_count = 0; - buffer_block* blocks[0]; + uint8_t block_count = 0; + buffer_block* blocks[0]; }; fast_lock_t chain_lock; block_chain* chain_head = nullptr; inline void destroy_block(buffer_block* block) { - block->block_lock.~fast_lock_t(); - free(block); + block->block_lock.~fast_lock_t(); + free(block); } inline buffer_block* allocate_block(size::value type) { - auto base_size = sizeof(buffer_block); - auto buffer_size = size::byte_length(type); - auto base_entry_size = sizeof(buffer_entry) + buffer_size; - auto size = base_size + BLOCK_BUFFERS * base_entry_size; + auto base_size = sizeof(buffer_block); + auto buffer_size = size::byte_length(type); + auto base_entry_size = sizeof(buffer_entry) + buffer_size; + auto size = base_size + BLOCK_BUFFERS * base_entry_size; - auto block = (buffer_block*) malloc(size); - new (&block->block_lock) fast_lock_t(); /* initialize spin lock */ + auto block = (buffer_block*) malloc(size); + new (&block->block_lock) fast_lock_t(); /* initialize spin lock */ #ifdef MEM_BLOCK_MAGIC - block->magic = MEM_BLOCK_MAGIC; + block->magic = MEM_BLOCK_MAGIC; #endif - block->type = type; + block->type = type; - for(uint8_t index = 0; index < BLOCK_BUFFERS; index++) { - auto entry_ptr = (uintptr_t) block->buffers + index * (uintptr_t) base_entry_size; - ((buffer_entry*) entry_ptr)->base_offset = index * (uintptr_t) base_entry_size + sizeof(buffer_block); - ((buffer_entry*) entry_ptr)->base_index = index; - } - block->flag_free = BLOCK_BUFFER_MASK; - return block; + for(uint8_t index = 0; index < BLOCK_BUFFERS; index++) { + auto entry_ptr = (uintptr_t) block->buffers + index * (uintptr_t) base_entry_size; + ((buffer_entry*) entry_ptr)->base_offset = index * (uintptr_t) base_entry_size + sizeof(buffer_block); + ((buffer_entry*) entry_ptr)->base_index = index; + } + block->flag_free = BLOCK_BUFFER_MASK; + return block; } inline void destroy_chain_entry(block_chain* chain) { - free(chain); + free(chain); } inline block_chain* allocate_chain_entry(uint8_t entries) { - auto base_size = sizeof(block_chain); - auto chain = (block_chain*) malloc(base_size + sizeof(void*) * entries); + auto base_size = sizeof(block_chain); + auto chain = (block_chain*) malloc(base_size + sizeof(void*) * entries); - chain->next = nullptr; - chain->previous = nullptr; - chain->block_count = entries; - for(auto& index : chain->type_index) - index = 0; - for(uint8_t index = 0; index < entries; index++) - chain->blocks[index] = nullptr; + chain->next = nullptr; + chain->previous = nullptr; + chain->block_count = entries; + for(auto& index : chain->type_index) + index = 0; + for(uint8_t index = 0; index < entries; index++) + chain->blocks[index] = nullptr; - return chain; + return chain; } struct BufferDeallocator { - bool operator()(void* buffer) { - buffer::release_buffer(buffer); - return true; - } + bool operator()(void* buffer) { + buffer::release_buffer(buffer); + return true; + } }; struct BufferAllocator { - bool operator()(size_t& /* length */, void*& /* result ptr */) { - __throw_logic_error("Cant reallocate a fixed buffer"); - } + bool operator()(size_t& /* length */, void*& /* result ptr */) { + __throw_logic_error("Cant reallocate a fixed buffer"); + } }; buffer_t buffer::allocate_buffer(size::value size) { - return pipes::buffer{size}; + return pipes::buffer{size}; - fast_lock_t* block_lock = nullptr; - buffer_block* block; + fast_lock_t* block_lock = nullptr; + buffer_block* block; - { - block_chain* tmp_chain; + { + block_chain* tmp_chain; - lock_guard lock_chain(chain_lock); - auto head = chain_head; + lock_guard lock_chain(chain_lock); + auto head = chain_head; - auto type_index = (size::value) (size - size::min); - iterate_head: - while(head) { - uint8_t& index = head->type_index[type_index]; - while(index < head->block_count) { - auto entry = head->blocks[index]; - if(entry) { - if(entry->type != size || (entry->flag_free & BLOCK_BUFFER_MASK) == 0) - goto next_block; + auto type_index = (size::value) (size - size::min); + iterate_head: + while(head) { + uint8_t& index = head->type_index[type_index]; + while(index < head->block_count) { + auto entry = head->blocks[index]; + if(entry) { + if(entry->type != size || (entry->flag_free & BLOCK_BUFFER_MASK) == 0) + goto next_block; - block_lock = &entry->block_lock; - if(!block_lock->try_lock() || (entry->flag_free & BLOCK_BUFFER_MASK) == 0) { - block_lock->unlock(); - goto next_block; - } + block_lock = &entry->block_lock; + if(!block_lock->try_lock() || (entry->flag_free & BLOCK_BUFFER_MASK) == 0) { + block_lock->unlock(); + goto next_block; + } - block = entry; - /* we've found an entry with a free block */ - goto break_head_loop; - } else { - /* lets insert a new block */ - head->blocks[index] = (entry = allocate_block(size)); - entry->chain_entry = head; - entry->block_index = index; + block = entry; + /* we've found an entry with a free block */ + goto break_head_loop; + } else { + /* lets insert a new block */ + head->blocks[index] = (entry = allocate_block(size)); + entry->chain_entry = head; + entry->block_index = index; - block_lock = &entry->block_lock; - block_lock->lock(); + block_lock = &entry->block_lock; + block_lock->lock(); - block = entry; - /* we've a new block which has to have free slots */ - goto break_head_loop; - } + block = entry; + /* we've a new block which has to have free slots */ + goto break_head_loop; + } - next_block: - index++; - } + next_block: + index++; + } - if(!head->next) - break; + if(!head->next) + break; - head = head->next; - } + head = head->next; + } - tmp_chain = allocate_chain_entry(128); - tmp_chain->previous = head; + tmp_chain = allocate_chain_entry(128); + tmp_chain->previous = head; - if(!head) { /* we've to create a chain head */ - chain_head = (head = tmp_chain); - } else { /* we've to append a new entry */ - head = (head->next = tmp_chain); - } - goto iterate_head; - /* insert new entry */ + if(!head) { /* we've to create a chain head */ + chain_head = (head = tmp_chain); + } else { /* we've to append a new entry */ + head = (head->next = tmp_chain); + } + goto iterate_head; + /* insert new entry */ - break_head_loop:; - } + break_head_loop:; + } - auto index = __builtin_ctz(block->flag_free); - block->flag_free &= ~(1 << index); - block_lock->unlock(); + auto index = __builtin_ctz(block->flag_free); + block->flag_free &= ~(1 << index); + block_lock->unlock(); - auto buffer_size = size::byte_length(size); - auto buffer_entry_size = buffer_size + sizeof(buffer_entry_head); - auto entry = (buffer_entry_head*) ((uintptr_t) block->buffers + (uintptr_t) buffer_entry_size * index); + auto buffer_size = size::byte_length(size); + auto buffer_entry_size = buffer_size + sizeof(buffer_entry_head); + auto entry = (buffer_entry_head*) ((uintptr_t) block->buffers + (uintptr_t) buffer_entry_size * index); #ifdef MEM_BUFFER_MAGIC - entry->magic = MEM_BUFFER_MAGIC; + entry->magic = MEM_BUFFER_MAGIC; #endif - return pipes::buffer{(void*) entry, buffer_entry_size, false, BufferAllocator(), BufferDeallocator()}.range(sizeof(buffer_entry_head)); + return pipes::buffer{(void*) entry, buffer_entry_size, false, BufferAllocator(), BufferDeallocator()}.range(sizeof(buffer_entry_head)); } inline bool valid_buffer_size(size_t size) { - return size == 512 || size == 1024 || size == 1536; + return size == 512 || size == 1024 || size == 1536; } void buffer::release_buffer(void *buffer) { - return; + return; - auto head = (buffer_entry_head*) buffer; + auto head = (buffer_entry_head*) buffer; #ifdef MEM_BUFFER_MAGIC - assert(head->magic == MEM_BUFFER_MAGIC); + assert(head->magic == MEM_BUFFER_MAGIC); #endif - auto block = (buffer_block*) ((uintptr_t) head - (uintptr_t) head->base_offset); + auto block = (buffer_block*) ((uintptr_t) head - (uintptr_t) head->base_offset); #ifdef MEM_BLOCK_MAGIC - assert(block->magic == MEM_BLOCK_MAGIC); + assert(block->magic == MEM_BLOCK_MAGIC); #endif - block->flag_free |= (1 << head->base_index); /* set the slot free flag */ + block->flag_free |= (1 << head->base_index); /* set the slot free flag */ - auto type_index = (size::value) (block->type - size::min); - auto& index = block->chain_entry->type_index[type_index]; - if(index > block->block_index) - index = block->block_index; + auto type_index = (size::value) (block->type - size::min); + auto& index = block->chain_entry->type_index[type_index]; + if(index > block->block_index) + index = block->block_index; } void buffer::release_buffer(pipes::buffer *buffer) { - assert(buffer->capacity_origin() > sizeof(buffer_entry_head)); - assert(valid_buffer_size(buffer->capacity_origin() - sizeof(buffer_entry_head))); + assert(buffer->capacity_origin() > sizeof(buffer_entry_head)); + assert(valid_buffer_size(buffer->capacity_origin() - sizeof(buffer_entry_head))); - release_buffer(buffer->data_ptr_origin()); - delete buffer; + release_buffer(buffer->data_ptr_origin()); + delete buffer; } meminfo buffer::buffer_memory() { - size_t bytes_buffer = 0; - size_t bytes_buffer_used = 0; - size_t bytes_internal = 0; - size_t nodes = 0; - size_t nodes_full = 0; + size_t bytes_buffer = 0; + size_t bytes_buffer_used = 0; + size_t bytes_internal = 0; + size_t nodes = 0; + size_t nodes_full = 0; - { - lock_guard lock_chain(chain_lock); - auto head = chain_head; - bool full; - while(head) { - full = true; - nodes++; - bytes_internal += sizeof(chain_head) + sizeof(void*) * head->block_count; + { + lock_guard lock_chain(chain_lock); + auto head = chain_head; + bool full; + while(head) { + full = true; + nodes++; + bytes_internal += sizeof(chain_head) + sizeof(void*) * head->block_count; - for(uint8_t index = 0; index < head->block_count; index++) { - auto block = head->blocks[index]; - if(block) { - bytes_internal += sizeof(buffer_block); - bytes_internal += sizeof(buffer_entry) * BLOCK_BUFFERS; + for(uint8_t index = 0; index < head->block_count; index++) { + auto block = head->blocks[index]; + if(block) { + bytes_internal += sizeof(buffer_block); + bytes_internal += sizeof(buffer_entry) * BLOCK_BUFFERS; - full = full && (block->flag_free & BLOCK_BUFFER_MASK) == 0; - auto length = size::byte_length(block->type); - bytes_buffer += length * BLOCK_BUFFERS; - bytes_buffer_used += (BLOCK_BUFFERS - __builtin_popcount(block->flag_free & BLOCK_BUFFER_MASK)) * length; - } else - full = false; - } + full = full && (block->flag_free & BLOCK_BUFFER_MASK) == 0; + auto length = size::byte_length(block->type); + bytes_buffer += length * BLOCK_BUFFERS; + bytes_buffer_used += (BLOCK_BUFFERS - __builtin_popcount(block->flag_free & BLOCK_BUFFER_MASK)) * length; + } else + full = false; + } - head = head->next; - } - } + head = head->next; + } + } - return {bytes_buffer, bytes_buffer_used, bytes_internal, nodes, nodes_full}; + return {bytes_buffer, bytes_buffer_used, bytes_internal, nodes, nodes_full}; } cleaninfo buffer::cleanup_buffers(cleanmode::value mode) { - std::deque orphaned_blocks; - std::deque orphaned_chunks; + std::deque orphaned_blocks; + std::deque orphaned_chunks; - bool flag_blocks = (mode & cleanmode::BLOCKS) > 0; - bool flag_chunks = (mode & cleanmode::CHUNKS) > 0; - { - lock_guard lock_chain(chain_lock); + bool flag_blocks = (mode & cleanmode::BLOCKS) > 0; + bool flag_chunks = (mode & cleanmode::CHUNKS) > 0; + { + lock_guard lock_chain(chain_lock); - auto head = chain_head; - uint32_t free_value = BLOCK_BUFFER_MASK; - vector> block_locks; + auto head = chain_head; + uint32_t free_value = BLOCK_BUFFER_MASK; + vector> block_locks; - while(head) { - bool flag_used = false; + while(head) { + bool flag_used = false; - if(flag_blocks) { - for(uint8_t index = 0; index < head->block_count; index++) { - auto block = head->blocks[index]; - if(!block) continue; /* block isn't set */ + if(flag_blocks) { + for(uint8_t index = 0; index < head->block_count; index++) { + auto block = head->blocks[index]; + if(!block) continue; /* block isn't set */ - if(block->flag_free == free_value) { - lock_guard block_lock(block->block_lock); - if(block->flag_free != free_value) { /* block had been used while locking */ - flag_used |= true; - continue; - } + if(block->flag_free == free_value) { + lock_guard block_lock(block->block_lock); + if(block->flag_free != free_value) { /* block had been used while locking */ + flag_used |= true; + continue; + } - head->blocks[index] = nullptr; - orphaned_blocks.push_back(block); - } else { - flag_used |= true; - } - } - } + head->blocks[index] = nullptr; + orphaned_blocks.push_back(block); + } else { + flag_used |= true; + } + } + } - if(flag_chunks) { - if(!flag_blocks) { /* we've to calculate flag_used */ - block_locks.resize(head->block_count); + if(flag_chunks) { + if(!flag_blocks) { /* we've to calculate flag_used */ + block_locks.resize(head->block_count); - for(uint8_t index = 0; index < head->block_count; index++) { - auto block = head->blocks[index]; - if(block) { - block_locks[index] = unique_lock{block->block_lock}; - if(block->flag_free == free_value) { - /* delete that block later */ - continue; - } + for(uint8_t index = 0; index < head->block_count; index++) { + auto block = head->blocks[index]; + if(block) { + block_locks[index] = unique_lock{block->block_lock}; + if(block->flag_free == free_value) { + /* delete that block later */ + continue; + } - flag_used = true; - break; - } - } - } + flag_used = true; + break; + } + } + } - if(!flag_used) { - if(head->previous) - head->previous->next = head->next; - else if(head == chain_head) - chain_head = head->next; + if(!flag_used) { + if(head->previous) + head->previous->next = head->next; + else if(head == chain_head) + chain_head = head->next; - if(head->next) - head->next->previous = head->previous; + if(head->next) + head->next->previous = head->previous; - orphaned_chunks.push_back(head); - } + orphaned_chunks.push_back(head); + } - block_locks.clear(); - } + block_locks.clear(); + } - head = head->next; - } - } + head = head->next; + } + } - size_t bytes_internal = 0; - size_t bytes_buffer = 0; + size_t bytes_internal = 0; + size_t bytes_buffer = 0; - for(auto chain : orphaned_chunks) { - for(uint8_t index = 0; index < chain->block_count; index++) { - if(chain->blocks[index]) - orphaned_blocks.push_back(chain->blocks[index]); - } - bytes_internal += sizeof(block_chain); + for(auto chain : orphaned_chunks) { + for(uint8_t index = 0; index < chain->block_count; index++) { + if(chain->blocks[index]) + orphaned_blocks.push_back(chain->blocks[index]); + } + bytes_internal += sizeof(block_chain); - destroy_chain_entry(chain); - } + destroy_chain_entry(chain); + } - for(auto block : orphaned_blocks) { - bytes_buffer += size::byte_length(block->type) * BLOCK_BUFFERS; - bytes_internal += sizeof(buffer_entry_head) * BLOCK_BUFFERS; - bytes_internal += sizeof(buffer_block); + for(auto block : orphaned_blocks) { + bytes_buffer += size::byte_length(block->type) * BLOCK_BUFFERS; + bytes_internal += sizeof(buffer_entry_head) * BLOCK_BUFFERS; + bytes_internal += sizeof(buffer_block); - destroy_block(block); - } + destroy_block(block); + } - return {bytes_internal, bytes_buffer}; + return {bytes_internal, bytes_buffer}; } \ No newline at end of file diff --git a/src/protocol/buffers_allocator_b.cpp b/src/protocol/buffers_allocator_b.cpp index 0c2b9fb..c8d1067 100644 --- a/src/protocol/buffers_allocator_b.cpp +++ b/src/protocol/buffers_allocator_b.cpp @@ -9,171 +9,171 @@ using namespace ts::buffer; #pragma GCC optimize ("O3") class spin_lock { - std::atomic_flag locked = ATOMIC_FLAG_INIT; - public: - void lock() { - uint8_t round = 0; - while (locked.test_and_set(std::memory_order_acquire)) { - //Yield when we're using this lock for a longer time, which we usually not doing - if(round++ % 8 == 0) - std::this_thread::yield(); - } - } + std::atomic_flag locked = ATOMIC_FLAG_INIT; + public: + void lock() { + uint8_t round = 0; + while (locked.test_and_set(std::memory_order_acquire)) { + //Yield when we're using this lock for a longer time, which we usually not doing + if(round++ % 8 == 0) + std::this_thread::yield(); + } + } - inline bool try_lock() { - return !locked.test_and_set(std::memory_order_acquire); - } + inline bool try_lock() { + return !locked.test_and_set(std::memory_order_acquire); + } - void unlock() { - locked.clear(std::memory_order_release); - } + void unlock() { + locked.clear(std::memory_order_release); + } }; typedef spin_lock fast_lock_t; struct BufferAllocator { - bool operator()(size_t& length, void*& result) { - __throw_logic_error("Cant reallocate a fixed buffer"); - } + bool operator()(size_t& length, void*& result) { + __throw_logic_error("Cant reallocate a fixed buffer"); + } }; struct Freelist { - struct Buffer { - Buffer* next_buffer; - char data_ptr[0]; - }; + struct Buffer { + Buffer* next_buffer; + char data_ptr[0]; + }; - std::function deallocator; - BufferAllocator allocator{}; + std::function deallocator; + BufferAllocator allocator{}; - fast_lock_t lock{}; + fast_lock_t lock{}; - Buffer* head = nullptr; - Buffer* tail = nullptr; - ssize_t length = 0; + Buffer* head = nullptr; + Buffer* tail = nullptr; + ssize_t length = 0; - size_t buffer_size; - ssize_t max_length; + size_t buffer_size; + ssize_t max_length; #ifdef DEBUG_FREELIST - std::atomic extra_alloc = 0; - std::atomic extra_free = 0; + std::atomic extra_alloc = 0; + std::atomic extra_free = 0; - std::atomic total_alloc = 0; - std::atomic total_free = 0; + std::atomic total_alloc = 0; + std::atomic total_free = 0; #endif - pipes::buffer next_buffer() { + pipes::buffer next_buffer() { #ifdef DEBUG_FREELIST - this->total_alloc++; + this->total_alloc++; #endif - Buffer* buffer = nullptr; - { - lock_guard lock(this->lock); - if(this->head) { - buffer = this->head; - if(buffer == this->tail) { - this->tail = nullptr; - this->head = nullptr; - assert(this->length == 0); - } else { - this->head = buffer->next_buffer; - assert(this->length > 0); - } - this->length--; - } - } - if(!buffer) { + Buffer* buffer = nullptr; + { + lock_guard lock(this->lock); + if(this->head) { + buffer = this->head; + if(buffer == this->tail) { + this->tail = nullptr; + this->head = nullptr; + assert(this->length == 0); + } else { + this->head = buffer->next_buffer; + assert(this->length > 0); + } + this->length--; + } + } + if(!buffer) { #ifdef DEBUG_FREELIST - this->extra_alloc++; + this->extra_alloc++; #endif - buffer = (Buffer*) malloc(sizeof(Buffer) + this->buffer_size); - } + buffer = (Buffer*) malloc(sizeof(Buffer) + this->buffer_size); + } - return pipes::buffer{(void*) buffer, this->buffer_size + sizeof(Buffer), false, allocator, deallocator}.range(sizeof(Buffer)); - } + return pipes::buffer{(void*) buffer, this->buffer_size + sizeof(Buffer), false, allocator, deallocator}.range(sizeof(Buffer)); + } - bool release_buffer(void* ptr) { + bool release_buffer(void* ptr) { #ifdef DEBUG_FREELIST - this->total_free++; + this->total_free++; #endif - auto buffer = (Buffer*) ptr; + auto buffer = (Buffer*) ptr; - if(this->max_length > 0 && this->length > this->max_length) { - /* dont push anymore stuff into the freelist! */ + if(this->max_length > 0 && this->length > this->max_length) { + /* dont push anymore stuff into the freelist! */ #ifdef DEBUG_FREELIST - this->extra_free++; + this->extra_free++; #endif - free(ptr); - return true; - } + free(ptr); + return true; + } - { - lock_guard lock(this->lock); - if(this->tail) { - this->tail->next_buffer = buffer; - } else { - this->head = buffer; - } - this->tail = buffer; - buffer->next_buffer = nullptr; + { + lock_guard lock(this->lock); + if(this->tail) { + this->tail->next_buffer = buffer; + } else { + this->head = buffer; + } + this->tail = buffer; + buffer->next_buffer = nullptr; - this->length++; - } + this->length++; + } - return true; - } + return true; + } - cleaninfo cleanup() { - size_t buffers_deallocated = 0; + cleaninfo cleanup() { + size_t buffers_deallocated = 0; - { - lock_guard lock(this->lock); - while(this->head) { - auto buffer = this->head; - this->head = buffer->next_buffer; - free(buffer); + { + lock_guard lock(this->lock); + while(this->head) { + auto buffer = this->head; + this->head = buffer->next_buffer; + free(buffer); - buffers_deallocated++; - } + buffers_deallocated++; + } - this->tail = nullptr; - this->head = nullptr; - this->length = 0; - } + this->tail = nullptr; + this->head = nullptr; + this->length = 0; + } - return {buffers_deallocated * 8, buffers_deallocated * this->buffer_size}; - } + return {buffers_deallocated * 8, buffers_deallocated * this->buffer_size}; + } - explicit Freelist(size_t size) { - this->buffer_size = size; - this->max_length = 1024 * 1024 * 1024; /* 1GB */ - this->deallocator = bind(&Freelist::release_buffer, this, placeholders::_1); - } + explicit Freelist(size_t size) { + this->buffer_size = size; + this->max_length = 1024 * 1024 * 1024; /* 1GB */ + this->deallocator = bind(&Freelist::release_buffer, this, placeholders::_1); + } }; Freelist freelists[size::max - size::min] = { - Freelist(size::byte_length(size::Bytes_512)), - Freelist(size::byte_length(size::Bytes_1024)), - Freelist(size::byte_length(size::Bytes_1536)) + Freelist(size::byte_length(size::Bytes_512)), + Freelist(size::byte_length(size::Bytes_1024)), + Freelist(size::byte_length(size::Bytes_1536)) }; buffer_t buffer::allocate_buffer(size::value size) { - assert((size - size::min) > 0 && (size - size::min) < (size::max - size::min)); - return freelists[size - size::min].next_buffer(); + assert((size - size::min) > 0 && (size - size::min) < (size::max - size::min)); + return freelists[size - size::min].next_buffer(); } cleaninfo& operator+=(cleaninfo& self, const cleaninfo& other) { - self.bytes_freed_internal += other.bytes_freed_internal; - self.bytes_freed_buffer += other.bytes_freed_buffer; - return self; + self.bytes_freed_internal += other.bytes_freed_internal; + self.bytes_freed_buffer += other.bytes_freed_buffer; + return self; } cleaninfo buffer::cleanup_buffers(cleanmode::value mode) { - cleaninfo info{0, 0}; - info += freelists[0].cleanup(); - info += freelists[1].cleanup(); - info += freelists[2].cleanup(); - return info; + cleaninfo info{0, 0}; + info += freelists[0].cleanup(); + info += freelists[1].cleanup(); + info += freelists[2].cleanup(); + return info; } //cleanup_buffers //$4 = {bytes_freed_internal = 8389144, bytes_freed_buffer = 536948736} \ No newline at end of file diff --git a/src/protocol/buffers_allocator_c.cpp b/src/protocol/buffers_allocator_c.cpp index 20cb740..959e1a2 100644 --- a/src/protocol/buffers_allocator_c.cpp +++ b/src/protocol/buffers_allocator_c.cpp @@ -10,9 +10,9 @@ using namespace ts::buffer; #endif buffer_t buffer::allocate_buffer(size::value size) { - return pipes::buffer{buffer::size::byte_length(size)}; + return pipes::buffer{buffer::size::byte_length(size)}; } cleaninfo buffer::cleanup_buffers(cleanmode::value mode) { - return {0, 0}; + return {0, 0}; } \ No newline at end of file diff --git a/src/protocol/ringbuffer.h b/src/protocol/ringbuffer.h index 74e2243..9f41e0a 100644 --- a/src/protocol/ringbuffer.h +++ b/src/protocol/ringbuffer.h @@ -13,219 +13,219 @@ #endif namespace ts { - namespace protocol { - template - struct RingEntry { - bool flag_set = false; - T entry{}; - }; + namespace protocol { + template + struct RingEntry { + bool flag_set = false; + T entry{}; + }; - template - class RingBuffer { - public: - static constexpr size_type _max_index = ~((size_type) 0); + template + class RingBuffer { + public: + static constexpr size_type _max_index = ~((size_type) 0); - RingBuffer() : _capacity(capacity_t) { - this->_ring_index_full = 0; - this->_ring_base_index = 0; - } + RingBuffer() : _capacity(capacity_t) { + this->_ring_index_full = 0; + this->_ring_base_index = 0; + } - inline size_type current_index() { return this->_ring_index; } + inline size_type current_index() { return this->_ring_index; } - /** - * @param index - * @return -1 underflow | 0 success | 1 overflow - */ - inline int accept_index(size_type index) { - size_t relative_index; - if(this->calculate_index(index, relative_index)) - return 0; - if(index < this->current_index()) - return -1; - return 1; - } + /** + * @param index + * @return -1 underflow | 0 success | 1 overflow + */ + inline int accept_index(size_type index) { + size_t relative_index; + if(this->calculate_index(index, relative_index)) + return 0; + if(index < this->current_index()) + return -1; + return 1; + } - inline bool index_set(size_type index) { - size_t relative_index = 0; - if(!this->calculate_index(index, relative_index)) - return false; - return this->index(relative_index).flag_set; - } + inline bool index_set(size_type index) { + size_t relative_index = 0; + if(!this->calculate_index(index, relative_index)) + return false; + return this->index(relative_index).flag_set; + } - inline E& index_value(size_type index) { - size_t relative_index = 0; - if(!this->calculate_index(index, relative_index)) - return {}; + inline E& index_value(size_type index) { + size_t relative_index = 0; + if(!this->calculate_index(index, relative_index)) + return {}; - return this->index(relative_index).entry; - } + return this->index(relative_index).entry; + } - inline size_t current_slot() { return this->_ring_base_index; } + inline size_t current_slot() { return this->_ring_base_index; } - inline bool slot_set(size_t slot) { - return this->index(slot).flag_set; - } + inline bool slot_set(size_t slot) { + return this->index(slot).flag_set; + } - inline E& slot_value(size_t slot) { - return this->index(slot).entry; - } + inline E& slot_value(size_t slot) { + return this->index(slot).entry; + } - inline bool front_set() { return this->_slots[this->_ring_base_index].flag_set; } + inline bool front_set() { return this->_slots[this->_ring_base_index].flag_set; } - inline E pop_front() { - auto& slot = this->_slots[this->_ring_base_index]; - slot.flag_set = false; - auto entry = std::move(slot.entry); - this->_ring_base_index += 1; - this->_ring_index_full += 1; - if(this->_ring_base_index >= this->_capacity) - this->_ring_base_index -= this->_capacity; - return entry; - } + inline E pop_front() { + auto& slot = this->_slots[this->_ring_base_index]; + slot.flag_set = false; + auto entry = std::move(slot.entry); + this->_ring_base_index += 1; + this->_ring_index_full += 1; + if(this->_ring_base_index >= this->_capacity) + this->_ring_base_index -= this->_capacity; + return entry; + } - inline void push_front(E&& entry) { - /* go to the back of the ring and set this as front */ - if(this->_ring_base_index == 0) - this->_ring_base_index = (size_type) this->_capacity; + inline void push_front(E&& entry) { + /* go to the back of the ring and set this as front */ + if(this->_ring_base_index == 0) + this->_ring_base_index = (size_type) this->_capacity; - this->_ring_base_index -= 1; - this->_ring_index_full -= 1; + this->_ring_base_index -= 1; + this->_ring_index_full -= 1; - auto& slot = this->_slots[this->_ring_base_index]; - slot.entry = std::forward(entry); - slot.flag_set = 1; - } + auto& slot = this->_slots[this->_ring_base_index]; + slot.entry = std::forward(entry); + slot.flag_set = 1; + } - inline bool push_back(E&& entry) { - size_t count = 0; - size_t index = this->_ring_base_index; - while(count < this->_capacity) { - if(index >= this->_capacity) - index -= this->_capacity; + inline bool push_back(E&& entry) { + size_t count = 0; + size_t index = this->_ring_base_index; + while(count < this->_capacity) { + if(index >= this->_capacity) + index -= this->_capacity; - auto& slot = this->_slots[index]; - if(slot.flag_set) { - count++; - index++; - continue; - } + auto& slot = this->_slots[index]; + if(slot.flag_set) { + count++; + index++; + continue; + } - slot.entry = std::forward(entry); - slot.flag_set = 1; - break; - } + slot.entry = std::forward(entry); + slot.flag_set = 1; + break; + } - return count != this->_capacity; - } + return count != this->_capacity; + } - inline void set_full_index_to(size_type index) { - if(index > this->_ring_index) - this->_ring_index = index; - else if(index < 100 && this->_ring_index > std::numeric_limits::max() - 100) { - this->_ring_index_full += 200; /* let the index overflow into the generation counter */ - this->_ring_index = index; /* set the lower (16) bytes */ - } - } + inline void set_full_index_to(size_type index) { + if(index > this->_ring_index) + this->_ring_index = index; + else if(index < 100 && this->_ring_index > std::numeric_limits::max() - 100) { + this->_ring_index_full += 200; /* let the index overflow into the generation counter */ + this->_ring_index = index; /* set the lower (16) bytes */ + } + } - inline bool insert_index(size_type index, E&& entry) { - size_t relative_index = 0; - if(!this->calculate_index(index, relative_index)) - return false; + inline bool insert_index(size_type index, E&& entry) { + size_t relative_index = 0; + if(!this->calculate_index(index, relative_index)) + return false; - auto& slot = this->index(relative_index); - if(slot.flag_set) - return false; + auto& slot = this->index(relative_index); + if(slot.flag_set) + return false; - slot.entry = std::forward(entry); - slot.flag_set = true; - return true; - } + slot.entry = std::forward(entry); + slot.flag_set = true; + return true; + } - inline size_t capacity() { return this->_capacity; } + inline size_t capacity() { return this->_capacity; } - inline void clear() { - this->_ring_base_index = 0; - for(RingEntry& element : this->_slots) { - element.flag_set = false; - (void) std::move(element.entry); - } - } + inline void clear() { + this->_ring_base_index = 0; + for(RingEntry& element : this->_slots) { + element.flag_set = false; + (void) std::move(element.entry); + } + } - inline void reset() { - this->clear(); - this->_ring_index_full = 0; - } - protected: - size_t _capacity; - size_t _ring_base_index; /* index of slot 0 */ + inline void reset() { + this->clear(); + this->_ring_index_full = 0; + } + protected: + size_t _capacity; + size_t _ring_base_index; /* index of slot 0 */ - union { - uint64_t _ring_index_full; - struct { - static_assert(8 - sizeof(size_type) > 0, "Invalid size type!"); + union { + uint64_t _ring_index_full; + struct { + static_assert(8 - sizeof(size_type) > 0, "Invalid size type!"); - /* little endian */ - size_type _ring_index; /* index of the insert index | overflow is welcome here */ - uint8_t padding[8 - sizeof(size_type)]; - }; - }; + /* little endian */ + size_type _ring_index; /* index of the insert index | overflow is welcome here */ + uint8_t padding[8 - sizeof(size_type)]; + }; + }; - std::array, capacity_t> _slots; + std::array, capacity_t> _slots; - inline RingEntry& index(size_t relative_index) { - assert(relative_index < this->_capacity); - auto index = this->_ring_base_index + relative_index; - if(index >= this->_capacity) - index -= this->_capacity; - return this->_slots[index]; - } + inline RingEntry& index(size_t relative_index) { + assert(relative_index < this->_capacity); + auto index = this->_ring_base_index + relative_index; + if(index >= this->_capacity) + index -= this->_capacity; + return this->_slots[index]; + } - inline bool calculate_index(size_type index, size_t& relative_index) { - if(this->_ring_index > index) { /* test if index is an overflow of the counter */ - if(index >= (size_type) (this->_ring_index + this->_capacity)) /* not anymore in bounds */ - return false; - else - relative_index = index + (_max_index - this->_ring_index + 1); - if(relative_index >= this->_capacity) - return false; - } else if(this->_ring_index < index) { - /* check upper bounds */ - relative_index = index - this->_ring_index; - if(relative_index >= this->_capacity) - return false; - } else { - /* index is equal, do nothing */ - relative_index = 0; - } - return true; - } - }; + inline bool calculate_index(size_type index, size_t& relative_index) { + if(this->_ring_index > index) { /* test if index is an overflow of the counter */ + if(index >= (size_type) (this->_ring_index + this->_capacity)) /* not anymore in bounds */ + return false; + else + relative_index = index + (_max_index - this->_ring_index + 1); + if(relative_index >= this->_capacity) + return false; + } else if(this->_ring_index < index) { + /* check upper bounds */ + relative_index = index - this->_ring_index; + if(relative_index >= this->_capacity) + return false; + } else { + /* index is equal, do nothing */ + relative_index = 0; + } + return true; + } + }; - template > - class PacketRingBuffer : public RingBuffer { - public: - std::recursive_timed_mutex buffer_lock; - std::recursive_timed_mutex execute_lock; + template > + class PacketRingBuffer : public RingBuffer { + public: + std::recursive_timed_mutex buffer_lock; + std::recursive_timed_mutex execute_lock; - inline uint16_t generation(uint16_t packet_id) { - size_t relative_index = 0; - if(!this->calculate_index(packet_id, relative_index)) - relative_index = 0; /* okey we dont give a fuck */ + inline uint16_t generation(uint16_t packet_id) { + size_t relative_index = 0; + if(!this->calculate_index(packet_id, relative_index)) + relative_index = 0; /* okey we dont give a fuck */ - return ((this->_ring_index_full + relative_index) >> 16) & 0xFFFF; - } + return ((this->_ring_index_full + relative_index) >> 16) & 0xFFFF; + } - inline void set_generation(uint16_t value) { - this->_ring_index_full = (value << 16) | (this->_ring_index_full & 0xFFFF); - } + inline void set_generation(uint16_t value) { + this->_ring_index_full = (value << 16) | (this->_ring_index_full & 0xFFFF); + } - inline void set_generation_packet(uint16_t generation, uint16_t packet) { - this->_ring_index_full = (generation << 16) | (packet & 0xFFFF); - } + inline void set_generation_packet(uint16_t generation, uint16_t packet) { + this->_ring_index_full = (generation << 16) | (packet & 0xFFFF); + } - inline uint64_t full_index() { return this->_ring_index_full; } - }; - } + inline uint64_t full_index() { return this->_ring_index_full; } + }; + } } \ No newline at end of file diff --git a/src/qlz/QuickLZ_L1.cpp b/src/qlz/QuickLZ_L1.cpp index a158e13..bb3edcf 100644 --- a/src/qlz/QuickLZ_L1.cpp +++ b/src/qlz/QuickLZ_L1.cpp @@ -28,7 +28,7 @@ #if QLZ_COMPRESSION_LEVEL == 1 && defined QLZ_PTR_64 && QLZ_STREAMING_BUFFER == 0 #define OFFSET_BASE source - #define CAST (ui32)(size_t) + #define CAST (ui32)(size_t) #else #define OFFSET_BASE 0 #define CAST @@ -57,9 +57,9 @@ int qlz_get_setting(int setting) #if QLZ_COMPRESSION_LEVEL == 1 static int same(const unsigned char *src, size_t n) { - while(n > 0 && *(src + n) == *src) - n--; - return n == 0 ? 1 : 0; + while(n > 0 && *(src + n) == *src) + n--; + return n == 0 ? 1 : 0; } #endif @@ -83,9 +83,9 @@ static void reset_table_decompress(qlz_state_decompress *state) (void)i; #if QLZ_COMPRESSION_LEVEL == 2 for(i = 0; i < QLZ_HASH_VALUES; i++) - { - state->hash_counter[i] = 0; - } + { + state->hash_counter[i] = 0; + } #endif } @@ -102,18 +102,18 @@ static __inline ui32 fast_read(void const *src, ui32 bytes) { #ifndef X86X64 unsigned char *p = (unsigned char*)src; - switch (bytes) - { - case 4: - return(*p | *(p + 1) << 8 | *(p + 2) << 16 | *(p + 3) << 24); - case 3: - return(*p | *(p + 1) << 8 | *(p + 2) << 16); - case 2: - return(*p | *(p + 1) << 8); - case 1: - return(*p); - } - return 0; + switch (bytes) + { + case 4: + return(*p | *(p + 1) << 8 | *(p + 2) << 16 | *(p + 3) << 24); + case 3: + return(*p | *(p + 1) << 8 | *(p + 2) << 16); + case 2: + return(*p | *(p + 1) << 8); + case 1: + return(*p); + } + return 0; #else if (bytes >= 1 && bytes <= 4) return *((ui32*)src); @@ -135,27 +135,27 @@ static __inline void fast_write(ui32 f, void *dst, size_t bytes) #ifndef X86X64 unsigned char *p = (unsigned char*)dst; - switch (bytes) - { - case 4: - *p = (unsigned char)f; - *(p + 1) = (unsigned char)(f >> 8); - *(p + 2) = (unsigned char)(f >> 16); - *(p + 3) = (unsigned char)(f >> 24); - return; - case 3: - *p = (unsigned char)f; - *(p + 1) = (unsigned char)(f >> 8); - *(p + 2) = (unsigned char)(f >> 16); - return; - case 2: - *p = (unsigned char)f; - *(p + 1) = (unsigned char)(f >> 8); - return; - case 1: - *p = (unsigned char)f; - return; - } + switch (bytes) + { + case 4: + *p = (unsigned char)f; + *(p + 1) = (unsigned char)(f >> 8); + *(p + 2) = (unsigned char)(f >> 16); + *(p + 3) = (unsigned char)(f >> 24); + return; + case 3: + *p = (unsigned char)f; + *(p + 1) = (unsigned char)(f >> 8); + *(p + 2) = (unsigned char)(f >> 16); + return; + case 2: + *p = (unsigned char)f; + *(p + 1) = (unsigned char)(f >> 8); + return; + case 1: + *p = (unsigned char)f; + return; + } #else switch (bytes) { @@ -199,12 +199,12 @@ static __inline void memcpy_up(unsigned char *dst, const unsigned char *src, ui3 // Caution if modifying memcpy_up! Overlap of dst and src must be special handled. #ifndef X86X64 unsigned char *end = dst + n; - while(dst < end) - { - *dst = *src; - dst++; - src++; - } + while(dst < end) + { + *dst = *src; + dst++; + src++; + } #else ui32 f = 0; do @@ -220,17 +220,17 @@ static __inline void update_hash(qlz_state_decompress *state, const unsigned cha { #if QLZ_COMPRESSION_LEVEL == 1 ui32 hash; - hash = hashat(s); - state->hash[hash].offset = s; - state->hash_counter[hash] = 1; + hash = hashat(s); + state->hash[hash].offset = s; + state->hash_counter[hash] = 1; #elif QLZ_COMPRESSION_LEVEL == 2 ui32 hash; - unsigned char c; - hash = hashat(s); - c = state->hash_counter[hash]; - state->hash[hash].offset[c & (QLZ_POINTERS - 1)] = s; - c++; - state->hash_counter[hash] = c; + unsigned char c; + hash = hashat(s); + c = state->hash_counter[hash]; + state->hash[hash].offset[c & (QLZ_POINTERS - 1)] = s; + c++; + state->hash_counter[hash] = c; #endif (void)state; (void)s; @@ -280,224 +280,224 @@ static size_t qlz_compress_core(const unsigned char *source, unsigned char *dest } #if QLZ_COMPRESSION_LEVEL == 1 { - const unsigned char *o; - ui32 hash, cached; + const unsigned char *o; + ui32 hash, cached; - hash = hash_func(fetch); - cached = fetch ^ state->hash[hash].cache; - state->hash[hash].cache = fetch; + hash = hash_func(fetch); + cached = fetch ^ state->hash[hash].cache; + state->hash[hash].cache = fetch; - o = state->hash[hash].offset + OFFSET_BASE; - state->hash[hash].offset = CAST(src - OFFSET_BASE); + o = state->hash[hash].offset + OFFSET_BASE; + state->hash[hash].offset = CAST(src - OFFSET_BASE); #ifdef X86X64 - if ((cached & 0xffffff) == 0 && o != OFFSET_BASE && (src - o > MINOFFSET || (src == o + 1 && lits >= 3 && src > source + 3 && same(src - 3, 6)))) - { - if(cached != 0) - { + if ((cached & 0xffffff) == 0 && o != OFFSET_BASE && (src - o > MINOFFSET || (src == o + 1 && lits >= 3 && src > source + 3 && same(src - 3, 6)))) + { + if(cached != 0) + { #else - if (cached == 0 && o != OFFSET_BASE && (src - o > MINOFFSET || (src == o + 1 && lits >= 3 && src > source + 3 && same(src - 3, 6)))) - { - if (*(o + 3) != *(src + 3)) - { + if (cached == 0 && o != OFFSET_BASE && (src - o > MINOFFSET || (src == o + 1 && lits >= 3 && src > source + 3 && same(src - 3, 6)))) + { + if (*(o + 3) != *(src + 3)) + { #endif - hash <<= 4; - cword_val = (cword_val >> 1) | (1U << 31); - fast_write((3 - 2) | hash, dst, 2); - src += 3; - dst += 2; - } - else - { - const unsigned char *old_src = src; - size_t matchlen; - hash <<= 4; + hash <<= 4; + cword_val = (cword_val >> 1) | (1U << 31); + fast_write((3 - 2) | hash, dst, 2); + src += 3; + dst += 2; + } + else + { + const unsigned char *old_src = src; + size_t matchlen; + hash <<= 4; - cword_val = (cword_val >> 1) | (1U << 31); - src += 4; + cword_val = (cword_val >> 1) | (1U << 31); + src += 4; - if(*(o + (src - old_src)) == *src) - { - src++; - if(*(o + (src - old_src)) == *src) - { - size_t q = last_byte - UNCOMPRESSED_END - (src - 5) + 1; - size_t remaining = q > 255 ? 255 : q; - src++; - while(*(o + (src - old_src)) == *src && (size_t)(src - old_src) < remaining) - src++; - } - } + if(*(o + (src - old_src)) == *src) + { + src++; + if(*(o + (src - old_src)) == *src) + { + size_t q = last_byte - UNCOMPRESSED_END - (src - 5) + 1; + size_t remaining = q > 255 ? 255 : q; + src++; + while(*(o + (src - old_src)) == *src && (size_t)(src - old_src) < remaining) + src++; + } + } - matchlen = src - old_src; - if (matchlen < 18) - { - fast_write((ui32)(matchlen - 2) | hash, dst, 2); - dst += 2; - } - else - { - fast_write((ui32)(matchlen << 16) | hash, dst, 3); - dst += 3; - } - } - fetch = fast_read(src, 3); - lits = 0; - } - else - { - lits++; - *dst = *src; - src++; - dst++; - cword_val = (cword_val >> 1); + matchlen = src - old_src; + if (matchlen < 18) + { + fast_write((ui32)(matchlen - 2) | hash, dst, 2); + dst += 2; + } + else + { + fast_write((ui32)(matchlen << 16) | hash, dst, 3); + dst += 3; + } + } + fetch = fast_read(src, 3); + lits = 0; + } + else + { + lits++; + *dst = *src; + src++; + dst++; + cword_val = (cword_val >> 1); #ifdef X86X64 - fetch = fast_read(src, 3); + fetch = fast_read(src, 3); #else - fetch = (fetch >> 8 & 0xffff) | (*(src + 2) << 16); + fetch = (fetch >> 8 & 0xffff) | (*(src + 2) << 16); #endif - } - } + } + } #elif QLZ_COMPRESSION_LEVEL >= 2 { - const unsigned char *o, *offset2; - ui32 hash, matchlen, k, m, best_k = 0; - unsigned char c; - size_t remaining = (last_byte - UNCOMPRESSED_END - src + 1) > 255 ? 255 : (last_byte - UNCOMPRESSED_END - src + 1); - (void)best_k; + const unsigned char *o, *offset2; + ui32 hash, matchlen, k, m, best_k = 0; + unsigned char c; + size_t remaining = (last_byte - UNCOMPRESSED_END - src + 1) > 255 ? 255 : (last_byte - UNCOMPRESSED_END - src + 1); + (void)best_k; - //hash = hashat(src); - fetch = fast_read(src, 3); - hash = hash_func(fetch); + //hash = hashat(src); + fetch = fast_read(src, 3); + hash = hash_func(fetch); - c = state->hash_counter[hash]; + c = state->hash_counter[hash]; - offset2 = state->hash[hash].offset[0]; - if(offset2 < src - MINOFFSET && c > 0 && ((fast_read(offset2, 3) ^ fetch) & 0xffffff) == 0) - { - matchlen = 3; - if(*(offset2 + matchlen) == *(src + matchlen)) - { - matchlen = 4; - while(*(offset2 + matchlen) == *(src + matchlen) && matchlen < remaining) - matchlen++; - } - } - else - matchlen = 0; - for(k = 1; k < QLZ_POINTERS && c > k; k++) - { - o = state->hash[hash].offset[k]; + offset2 = state->hash[hash].offset[0]; + if(offset2 < src - MINOFFSET && c > 0 && ((fast_read(offset2, 3) ^ fetch) & 0xffffff) == 0) + { + matchlen = 3; + if(*(offset2 + matchlen) == *(src + matchlen)) + { + matchlen = 4; + while(*(offset2 + matchlen) == *(src + matchlen) && matchlen < remaining) + matchlen++; + } + } + else + matchlen = 0; + for(k = 1; k < QLZ_POINTERS && c > k; k++) + { + o = state->hash[hash].offset[k]; #if QLZ_COMPRESSION_LEVEL == 3 - if(((fast_read(o, 3) ^ fetch) & 0xffffff) == 0 && o < src - MINOFFSET) + if(((fast_read(o, 3) ^ fetch) & 0xffffff) == 0 && o < src - MINOFFSET) #elif QLZ_COMPRESSION_LEVEL == 2 - if(*(src + matchlen) == *(o + matchlen) && ((fast_read(o, 3) ^ fetch) & 0xffffff) == 0 && o < src - MINOFFSET) + if(*(src + matchlen) == *(o + matchlen) && ((fast_read(o, 3) ^ fetch) & 0xffffff) == 0 && o < src - MINOFFSET) #endif - { - m = 3; - while(*(o + m) == *(src + m) && m < remaining) - m++; + { + m = 3; + while(*(o + m) == *(src + m) && m < remaining) + m++; #if QLZ_COMPRESSION_LEVEL == 3 - if ((m > matchlen) || (m == matchlen && o > offset2)) + if ((m > matchlen) || (m == matchlen && o > offset2)) #elif QLZ_COMPRESSION_LEVEL == 2 - if (m > matchlen) + if (m > matchlen) #endif - { - offset2 = o; - matchlen = m; - best_k = k; - } - } - } - o = offset2; - state->hash[hash].offset[c & (QLZ_POINTERS - 1)] = src; - c++; - state->hash_counter[hash] = c; + { + offset2 = o; + matchlen = m; + best_k = k; + } + } + } + o = offset2; + state->hash[hash].offset[c & (QLZ_POINTERS - 1)] = src; + c++; + state->hash_counter[hash] = c; #if QLZ_COMPRESSION_LEVEL == 3 - if(matchlen > 2 && src - o < 131071) - { - ui32 u; - size_t offset = src - o; + if(matchlen > 2 && src - o < 131071) + { + ui32 u; + size_t offset = src - o; - for(u = 1; u < matchlen; u++) - { - hash = hashat(src + u); - c = state->hash_counter[hash]++; - state->hash[hash].offset[c & (QLZ_POINTERS - 1)] = src + u; - } + for(u = 1; u < matchlen; u++) + { + hash = hashat(src + u); + c = state->hash_counter[hash]++; + state->hash[hash].offset[c & (QLZ_POINTERS - 1)] = src + u; + } - cword_val = (cword_val >> 1) | (1U << 31); - src += matchlen; + cword_val = (cword_val >> 1) | (1U << 31); + src += matchlen; - if(matchlen == 3 && offset <= 63) - { - *dst = (unsigned char)(offset << 2); - dst++; - } - else if (matchlen == 3 && offset <= 16383) - { - ui32 f = (ui32)((offset << 2) | 1); - fast_write(f, dst, 2); - dst += 2; - } - else if (matchlen <= 18 && offset <= 1023) - { - ui32 f = ((matchlen - 3) << 2) | ((ui32)offset << 6) | 2; - fast_write(f, dst, 2); - dst += 2; - } + if(matchlen == 3 && offset <= 63) + { + *dst = (unsigned char)(offset << 2); + dst++; + } + else if (matchlen == 3 && offset <= 16383) + { + ui32 f = (ui32)((offset << 2) | 1); + fast_write(f, dst, 2); + dst += 2; + } + else if (matchlen <= 18 && offset <= 1023) + { + ui32 f = ((matchlen - 3) << 2) | ((ui32)offset << 6) | 2; + fast_write(f, dst, 2); + dst += 2; + } - else if(matchlen <= 33) - { - ui32 f = ((matchlen - 2) << 2) | ((ui32)offset << 7) | 3; - fast_write(f, dst, 3); - dst += 3; - } - else - { - ui32 f = ((matchlen - 3) << 7) | ((ui32)offset << 15) | 3; - fast_write(f, dst, 4); - dst += 4; - } - } - else - { - *dst = *src; - src++; - dst++; - cword_val = (cword_val >> 1); - } + else if(matchlen <= 33) + { + ui32 f = ((matchlen - 2) << 2) | ((ui32)offset << 7) | 3; + fast_write(f, dst, 3); + dst += 3; + } + else + { + ui32 f = ((matchlen - 3) << 7) | ((ui32)offset << 15) | 3; + fast_write(f, dst, 4); + dst += 4; + } + } + else + { + *dst = *src; + src++; + dst++; + cword_val = (cword_val >> 1); + } #elif QLZ_COMPRESSION_LEVEL == 2 - if(matchlen > 2) - { - cword_val = (cword_val >> 1) | (1U << 31); - src += matchlen; + if(matchlen > 2) + { + cword_val = (cword_val >> 1) | (1U << 31); + src += matchlen; - if (matchlen < 10) - { - ui32 f = best_k | ((matchlen - 2) << 2) | (hash << 5); - fast_write(f, dst, 2); - dst += 2; - } - else - { - ui32 f = best_k | (matchlen << 16) | (hash << 5); - fast_write(f, dst, 3); - dst += 3; - } - } - else - { - *dst = *src; - src++; - dst++; - cword_val = (cword_val >> 1); - } + if (matchlen < 10) + { + ui32 f = best_k | ((matchlen - 2) << 2) | (hash << 5); + fast_write(f, dst, 2); + dst += 2; + } + else + { + ui32 f = best_k | (matchlen << 16) | (hash << 5); + fast_write(f, dst, 3); + dst += 3; + } + } + else + { + *dst = *src; + src++; + dst++; + cword_val = (cword_val >> 1); + } #endif - } + } #endif } while (src <= last_byte) @@ -514,18 +514,18 @@ static size_t qlz_compress_core(const unsigned char *source, unsigned char *dest { #if QLZ_COMPRESSION_LEVEL == 1 ui32 hash, fetch; - fetch = fast_read(src, 3); - hash = hash_func(fetch); - state->hash[hash].offset = CAST(src - OFFSET_BASE); - state->hash[hash].cache = fetch; + fetch = fast_read(src, 3); + hash = hash_func(fetch); + state->hash[hash].offset = CAST(src - OFFSET_BASE); + state->hash[hash].cache = fetch; #elif QLZ_COMPRESSION_LEVEL == 2 ui32 hash; - unsigned char c; - hash = hashat(src); - c = state->hash_counter[hash]; - state->hash[hash].offset[c & (QLZ_POINTERS - 1)] = src; - c++; - state->hash_counter[hash] = c; + unsigned char c; + hash = hashat(src); + c = state->hash_counter[hash]; + state->hash[hash].offset[c & (QLZ_POINTERS - 1)] = src; + c++; + state->hash_counter[hash] = c; #endif } #endif @@ -569,7 +569,7 @@ static size_t qlz_decompress_core(const unsigned char *source, unsigned char *de { #ifdef QLZ_MEMORY_SAFE if(src + CWORD_LEN - 1 > last_source_byte) - return 0; + return 0; #endif cword_val = fast_read(src, CWORD_LEN); src += CWORD_LEN; @@ -577,7 +577,7 @@ static size_t qlz_decompress_core(const unsigned char *source, unsigned char *de #ifdef QLZ_MEMORY_SAFE if(src + 4 - 1 > last_source_byte) - return 0; + return 0; #endif fetch = fast_read(src, 4); @@ -589,83 +589,83 @@ static size_t qlz_decompress_core(const unsigned char *source, unsigned char *de #if QLZ_COMPRESSION_LEVEL == 1 ui32 hash; - cword_val = cword_val >> 1; - hash = (fetch >> 4) & 0xfff; - offset2 = (const unsigned char *)(size_t)state->hash[hash].offset; + cword_val = cword_val >> 1; + hash = (fetch >> 4) & 0xfff; + offset2 = (const unsigned char *)(size_t)state->hash[hash].offset; - if((fetch & 0xf) != 0) - { - matchlen = (fetch & 0xf) + 2; - src += 2; - } - else - { - matchlen = *(src + 2); - src += 3; - } + if((fetch & 0xf) != 0) + { + matchlen = (fetch & 0xf) + 2; + src += 2; + } + else + { + matchlen = *(src + 2); + src += 3; + } #elif QLZ_COMPRESSION_LEVEL == 2 ui32 hash; - unsigned char c; - cword_val = cword_val >> 1; - hash = (fetch >> 5) & 0x7ff; - c = (unsigned char)(fetch & 0x3); - offset2 = state->hash[hash].offset[c]; + unsigned char c; + cword_val = cword_val >> 1; + hash = (fetch >> 5) & 0x7ff; + c = (unsigned char)(fetch & 0x3); + offset2 = state->hash[hash].offset[c]; - if((fetch & (28)) != 0) - { - matchlen = ((fetch >> 2) & 0x7) + 2; - src += 2; - } - else - { - matchlen = *(src + 2); - src += 3; - } + if((fetch & (28)) != 0) + { + matchlen = ((fetch >> 2) & 0x7) + 2; + src += 2; + } + else + { + matchlen = *(src + 2); + src += 3; + } #elif QLZ_COMPRESSION_LEVEL == 3 ui32 offset; - cword_val = cword_val >> 1; - if ((fetch & 3) == 0) - { - offset = (fetch & 0xff) >> 2; - matchlen = 3; - src++; - } - else if ((fetch & 2) == 0) - { - offset = (fetch & 0xffff) >> 2; - matchlen = 3; - src += 2; - } - else if ((fetch & 1) == 0) - { - offset = (fetch & 0xffff) >> 6; - matchlen = ((fetch >> 2) & 15) + 3; - src += 2; - } - else if ((fetch & 127) != 3) - { - offset = (fetch >> 7) & 0x1ffff; - matchlen = ((fetch >> 2) & 0x1f) + 2; - src += 3; - } - else - { - offset = (fetch >> 15); - matchlen = ((fetch >> 7) & 255) + 3; - src += 4; - } + cword_val = cword_val >> 1; + if ((fetch & 3) == 0) + { + offset = (fetch & 0xff) >> 2; + matchlen = 3; + src++; + } + else if ((fetch & 2) == 0) + { + offset = (fetch & 0xffff) >> 2; + matchlen = 3; + src += 2; + } + else if ((fetch & 1) == 0) + { + offset = (fetch & 0xffff) >> 6; + matchlen = ((fetch >> 2) & 15) + 3; + src += 2; + } + else if ((fetch & 127) != 3) + { + offset = (fetch >> 7) & 0x1ffff; + matchlen = ((fetch >> 2) & 0x1f) + 2; + src += 3; + } + else + { + offset = (fetch >> 15); + matchlen = ((fetch >> 7) & 255) + 3; + src += 4; + } - offset2 = dst - offset; + offset2 = dst - offset; #endif #ifdef QLZ_MEMORY_SAFE if(offset2 < history || offset2 > dst - MINOFFSET - 1) - return 0; + return 0; - if(matchlen > (ui32)(last_destination_byte - dst - UNCOMPRESSED_END + 1)) - return 0; + if(matchlen > (ui32)(last_destination_byte - dst - UNCOMPRESSED_END + 1)) + return 0; #endif memcpy_up(dst, offset2, matchlen); @@ -704,7 +704,7 @@ static size_t qlz_decompress_core(const unsigned char *source, unsigned char *de } #ifdef QLZ_MEMORY_SAFE if(src >= last_source_byte + 1) - return 0; + return 0; #endif *dst = *src; dst++; @@ -759,25 +759,25 @@ size_t qlz_compress(const void *source, char *destination, size_t size, qlz_stat } #if QLZ_STREAMING_BUFFER > 0 else - { - unsigned char *src = state->stream_buffer + state->stream_counter; + { + unsigned char *src = state->stream_buffer + state->stream_counter; - memcpy(src, source, size); - r = base + qlz_compress_core(src, (unsigned char*)destination + base, size, state); + memcpy(src, source, size); + r = base + qlz_compress_core(src, (unsigned char*)destination + base, size, state); - if(r == base) - { - memcpy(destination + base, src, size); - r = size + base; - compressed = 0; - reset_table_compress(state); - } - else - { - compressed = 1; - } - state->stream_counter += size; - } + if(r == base) + { + memcpy(destination + base, src, size); + r = size + base; + compressed = 0; + reset_table_compress(state); + } + else + { + compressed = 1; + } + state->stream_counter += size; + } #endif if(base == 3) { @@ -824,20 +824,20 @@ size_t qlz_decompress(const char *source, void *destination, qlz_state_decompres } #if QLZ_STREAMING_BUFFER > 0 else - { - unsigned char *dst = state->stream_buffer + state->stream_counter; - if((*source & 1) == 1) - { - dsiz = qlz_decompress_core((const unsigned char *)source, dst, dsiz, state, (const unsigned char *)state->stream_buffer); - } - else - { - memcpy(dst, source + qlz_size_header(source), dsiz); - reset_table_decompress(state); - } - memcpy(destination, dst, dsiz); - state->stream_counter += dsiz; - } + { + unsigned char *dst = state->stream_buffer + state->stream_counter; + if((*source & 1) == 1) + { + dsiz = qlz_decompress_core((const unsigned char *)source, dst, dsiz, state, (const unsigned char *)state->stream_buffer); + } + else + { + memcpy(dst, source + qlz_size_header(source), dsiz); + reset_table_decompress(state); + } + memcpy(destination, dst, dsiz); + state->stream_counter += dsiz; + } #endif return dsiz; } diff --git a/src/qlz/QuickLZ_L2.cpp b/src/qlz/QuickLZ_L2.cpp index aacfb79..586f977 100644 --- a/src/qlz/QuickLZ_L2.cpp +++ b/src/qlz/QuickLZ_L2.cpp @@ -27,7 +27,7 @@ #if QLZ_COMPRESSION_LEVEL == 1 && defined QLZ_PTR_64 && QLZ_STREAMING_BUFFER == 0 #define OFFSET_BASE source - #define CAST (ui32)(size_t) + #define CAST (ui32)(size_t) #else #define OFFSET_BASE 0 #define CAST @@ -56,9 +56,9 @@ int qlz_get_setting(int setting) #if QLZ_COMPRESSION_LEVEL == 1 static int same(const unsigned char *src, size_t n) { - while(n > 0 && *(src + n) == *src) - n--; - return n == 0 ? 1 : 0; + while(n > 0 && *(src + n) == *src) + n--; + return n == 0 ? 1 : 0; } #endif @@ -82,9 +82,9 @@ static void reset_table_decompress(qlz_state_decompress *state) (void)i; #if QLZ_COMPRESSION_LEVEL == 2 for(i = 0; i < QLZ_HASH_VALUES; i++) - { - state->hash_counter[i] = 0; - } + { + state->hash_counter[i] = 0; + } #endif } @@ -101,18 +101,18 @@ static __inline ui32 fast_read(void const *src, ui32 bytes) { #ifndef X86X64 unsigned char *p = (unsigned char*)src; - switch (bytes) - { - case 4: - return(*p | *(p + 1) << 8 | *(p + 2) << 16 | *(p + 3) << 24); - case 3: - return(*p | *(p + 1) << 8 | *(p + 2) << 16); - case 2: - return(*p | *(p + 1) << 8); - case 1: - return(*p); - } - return 0; + switch (bytes) + { + case 4: + return(*p | *(p + 1) << 8 | *(p + 2) << 16 | *(p + 3) << 24); + case 3: + return(*p | *(p + 1) << 8 | *(p + 2) << 16); + case 2: + return(*p | *(p + 1) << 8); + case 1: + return(*p); + } + return 0; #else if (bytes >= 1 && bytes <= 4) return *((ui32*)src); @@ -134,27 +134,27 @@ static __inline void fast_write(ui32 f, void *dst, size_t bytes) #ifndef X86X64 unsigned char *p = (unsigned char*)dst; - switch (bytes) - { - case 4: - *p = (unsigned char)f; - *(p + 1) = (unsigned char)(f >> 8); - *(p + 2) = (unsigned char)(f >> 16); - *(p + 3) = (unsigned char)(f >> 24); - return; - case 3: - *p = (unsigned char)f; - *(p + 1) = (unsigned char)(f >> 8); - *(p + 2) = (unsigned char)(f >> 16); - return; - case 2: - *p = (unsigned char)f; - *(p + 1) = (unsigned char)(f >> 8); - return; - case 1: - *p = (unsigned char)f; - return; - } + switch (bytes) + { + case 4: + *p = (unsigned char)f; + *(p + 1) = (unsigned char)(f >> 8); + *(p + 2) = (unsigned char)(f >> 16); + *(p + 3) = (unsigned char)(f >> 24); + return; + case 3: + *p = (unsigned char)f; + *(p + 1) = (unsigned char)(f >> 8); + *(p + 2) = (unsigned char)(f >> 16); + return; + case 2: + *p = (unsigned char)f; + *(p + 1) = (unsigned char)(f >> 8); + return; + case 1: + *p = (unsigned char)f; + return; + } #else switch (bytes) { @@ -205,12 +205,12 @@ static __inline void memcpy_up(unsigned char *dst, const unsigned char *src, ui3 // Caution if modifying memcpy_up! Overlap of dst and src must be special handled. #ifndef X86X64 unsigned char *end = dst + n; - while(dst < end) - { - *dst = *src; - dst++; - src++; - } + while(dst < end) + { + *dst = *src; + dst++; + src++; + } #else ui32 f = 0; do @@ -226,17 +226,17 @@ static __inline void update_hash(qlz_state_decompress *state, const unsigned cha { #if QLZ_COMPRESSION_LEVEL == 1 ui32 hash; - hash = hashat(s); - state->hash[hash].offset = s; - state->hash_counter[hash] = 1; + hash = hashat(s); + state->hash[hash].offset = s; + state->hash_counter[hash] = 1; #elif QLZ_COMPRESSION_LEVEL == 2 ui32 hash; - unsigned char c; - hash = hashat(s); - c = state->hash_counter[hash]; - state->hash[hash].offset[c & (QLZ_POINTERS - 1)] = s; - c++; - state->hash_counter[hash] = c; + unsigned char c; + hash = hashat(s); + c = state->hash_counter[hash]; + state->hash[hash].offset[c & (QLZ_POINTERS - 1)] = s; + c++; + state->hash_counter[hash] = c; #endif (void)state; (void)s; @@ -286,224 +286,224 @@ static size_t qlz_compress_core(const unsigned char *source, unsigned char *dest } #if QLZ_COMPRESSION_LEVEL == 1 { - const unsigned char *o; - ui32 hash, cached; + const unsigned char *o; + ui32 hash, cached; - hash = hash_func(fetch); - cached = fetch ^ state->hash[hash].cache; - state->hash[hash].cache = fetch; + hash = hash_func(fetch); + cached = fetch ^ state->hash[hash].cache; + state->hash[hash].cache = fetch; - o = state->hash[hash].offset + OFFSET_BASE; - state->hash[hash].offset = CAST(src - OFFSET_BASE); + o = state->hash[hash].offset + OFFSET_BASE; + state->hash[hash].offset = CAST(src - OFFSET_BASE); #ifdef X86X64 - if ((cached & 0xffffff) == 0 && o != OFFSET_BASE && (src - o > MINOFFSET || (src == o + 1 && lits >= 3 && src > source + 3 && same(src - 3, 6)))) - { - if(cached != 0) - { + if ((cached & 0xffffff) == 0 && o != OFFSET_BASE && (src - o > MINOFFSET || (src == o + 1 && lits >= 3 && src > source + 3 && same(src - 3, 6)))) + { + if(cached != 0) + { #else - if (cached == 0 && o != OFFSET_BASE && (src - o > MINOFFSET || (src == o + 1 && lits >= 3 && src > source + 3 && same(src - 3, 6)))) - { - if (*(o + 3) != *(src + 3)) - { + if (cached == 0 && o != OFFSET_BASE && (src - o > MINOFFSET || (src == o + 1 && lits >= 3 && src > source + 3 && same(src - 3, 6)))) + { + if (*(o + 3) != *(src + 3)) + { #endif - hash <<= 4; - cword_val = (cword_val >> 1) | (1U << 31); - fast_write((3 - 2) | hash, dst, 2); - src += 3; - dst += 2; - } - else - { - const unsigned char *old_src = src; - size_t matchlen; - hash <<= 4; + hash <<= 4; + cword_val = (cword_val >> 1) | (1U << 31); + fast_write((3 - 2) | hash, dst, 2); + src += 3; + dst += 2; + } + else + { + const unsigned char *old_src = src; + size_t matchlen; + hash <<= 4; - cword_val = (cword_val >> 1) | (1U << 31); - src += 4; + cword_val = (cword_val >> 1) | (1U << 31); + src += 4; - if(*(o + (src - old_src)) == *src) - { - src++; - if(*(o + (src - old_src)) == *src) - { - size_t q = last_byte - UNCOMPRESSED_END - (src - 5) + 1; - size_t remaining = q > 255 ? 255 : q; - src++; - while(*(o + (src - old_src)) == *src && (size_t)(src - old_src) < remaining) - src++; - } - } + if(*(o + (src - old_src)) == *src) + { + src++; + if(*(o + (src - old_src)) == *src) + { + size_t q = last_byte - UNCOMPRESSED_END - (src - 5) + 1; + size_t remaining = q > 255 ? 255 : q; + src++; + while(*(o + (src - old_src)) == *src && (size_t)(src - old_src) < remaining) + src++; + } + } - matchlen = src - old_src; - if (matchlen < 18) - { - fast_write((ui32)(matchlen - 2) | hash, dst, 2); - dst += 2; - } - else - { - fast_write((ui32)(matchlen << 16) | hash, dst, 3); - dst += 3; - } - } - fetch = fast_read(src, 3); - lits = 0; - } - else - { - lits++; - *dst = *src; - src++; - dst++; - cword_val = (cword_val >> 1); + matchlen = src - old_src; + if (matchlen < 18) + { + fast_write((ui32)(matchlen - 2) | hash, dst, 2); + dst += 2; + } + else + { + fast_write((ui32)(matchlen << 16) | hash, dst, 3); + dst += 3; + } + } + fetch = fast_read(src, 3); + lits = 0; + } + else + { + lits++; + *dst = *src; + src++; + dst++; + cword_val = (cword_val >> 1); #ifdef X86X64 - fetch = fast_read(src, 3); + fetch = fast_read(src, 3); #else - fetch = (fetch >> 8 & 0xffff) | (*(src + 2) << 16); + fetch = (fetch >> 8 & 0xffff) | (*(src + 2) << 16); #endif - } - } + } + } #elif QLZ_COMPRESSION_LEVEL >= 2 { - const unsigned char *o, *offset2; - ui32 hash, matchlen, k, m, best_k = 0; - unsigned char c; - size_t remaining = (last_byte - UNCOMPRESSED_END - src + 1) > 255 ? 255 : (last_byte - UNCOMPRESSED_END - src + 1); - (void)best_k; + const unsigned char *o, *offset2; + ui32 hash, matchlen, k, m, best_k = 0; + unsigned char c; + size_t remaining = (last_byte - UNCOMPRESSED_END - src + 1) > 255 ? 255 : (last_byte - UNCOMPRESSED_END - src + 1); + (void)best_k; - //hash = hashat(src); - fetch = fast_read(src, 3); - hash = hash_func(fetch); + //hash = hashat(src); + fetch = fast_read(src, 3); + hash = hash_func(fetch); - c = state->hash_counter[hash]; + c = state->hash_counter[hash]; - offset2 = state->hash[hash].offset[0]; - if(offset2 < src - MINOFFSET && c > 0 && ((fast_read(offset2, 3) ^ fetch) & 0xffffff) == 0) - { - matchlen = 3; - if(*(offset2 + matchlen) == *(src + matchlen)) - { - matchlen = 4; - while(*(offset2 + matchlen) == *(src + matchlen) && matchlen < remaining) - matchlen++; - } - } - else - matchlen = 0; - for(k = 1; k < QLZ_POINTERS && c > k; k++) - { - o = state->hash[hash].offset[k]; + offset2 = state->hash[hash].offset[0]; + if(offset2 < src - MINOFFSET && c > 0 && ((fast_read(offset2, 3) ^ fetch) & 0xffffff) == 0) + { + matchlen = 3; + if(*(offset2 + matchlen) == *(src + matchlen)) + { + matchlen = 4; + while(*(offset2 + matchlen) == *(src + matchlen) && matchlen < remaining) + matchlen++; + } + } + else + matchlen = 0; + for(k = 1; k < QLZ_POINTERS && c > k; k++) + { + o = state->hash[hash].offset[k]; #if QLZ_COMPRESSION_LEVEL == 3 - if(((fast_read(o, 3) ^ fetch) & 0xffffff) == 0 && o < src - MINOFFSET) + if(((fast_read(o, 3) ^ fetch) & 0xffffff) == 0 && o < src - MINOFFSET) #elif QLZ_COMPRESSION_LEVEL == 2 - if(*(src + matchlen) == *(o + matchlen) && ((fast_read(o, 3) ^ fetch) & 0xffffff) == 0 && o < src - MINOFFSET) + if(*(src + matchlen) == *(o + matchlen) && ((fast_read(o, 3) ^ fetch) & 0xffffff) == 0 && o < src - MINOFFSET) #endif - { - m = 3; - while(*(o + m) == *(src + m) && m < remaining) - m++; + { + m = 3; + while(*(o + m) == *(src + m) && m < remaining) + m++; #if QLZ_COMPRESSION_LEVEL == 3 - if ((m > matchlen) || (m == matchlen && o > offset2)) + if ((m > matchlen) || (m == matchlen && o > offset2)) #elif QLZ_COMPRESSION_LEVEL == 2 - if (m > matchlen) + if (m > matchlen) #endif - { - offset2 = o; - matchlen = m; - best_k = k; - } - } - } - o = offset2; - state->hash[hash].offset[c & (QLZ_POINTERS - 1)] = src; - c++; - state->hash_counter[hash] = c; + { + offset2 = o; + matchlen = m; + best_k = k; + } + } + } + o = offset2; + state->hash[hash].offset[c & (QLZ_POINTERS - 1)] = src; + c++; + state->hash_counter[hash] = c; #if QLZ_COMPRESSION_LEVEL == 3 - if(matchlen > 2 && src - o < 131071) - { - ui32 u; - size_t offset = src - o; + if(matchlen > 2 && src - o < 131071) + { + ui32 u; + size_t offset = src - o; - for(u = 1; u < matchlen; u++) - { - hash = hashat(src + u); - c = state->hash_counter[hash]++; - state->hash[hash].offset[c & (QLZ_POINTERS - 1)] = src + u; - } + for(u = 1; u < matchlen; u++) + { + hash = hashat(src + u); + c = state->hash_counter[hash]++; + state->hash[hash].offset[c & (QLZ_POINTERS - 1)] = src + u; + } - cword_val = (cword_val >> 1) | (1U << 31); - src += matchlen; + cword_val = (cword_val >> 1) | (1U << 31); + src += matchlen; - if(matchlen == 3 && offset <= 63) - { - *dst = (unsigned char)(offset << 2); - dst++; - } - else if (matchlen == 3 && offset <= 16383) - { - ui32 f = (ui32)((offset << 2) | 1); - fast_write(f, dst, 2); - dst += 2; - } - else if (matchlen <= 18 && offset <= 1023) - { - ui32 f = ((matchlen - 3) << 2) | ((ui32)offset << 6) | 2; - fast_write(f, dst, 2); - dst += 2; - } + if(matchlen == 3 && offset <= 63) + { + *dst = (unsigned char)(offset << 2); + dst++; + } + else if (matchlen == 3 && offset <= 16383) + { + ui32 f = (ui32)((offset << 2) | 1); + fast_write(f, dst, 2); + dst += 2; + } + else if (matchlen <= 18 && offset <= 1023) + { + ui32 f = ((matchlen - 3) << 2) | ((ui32)offset << 6) | 2; + fast_write(f, dst, 2); + dst += 2; + } - else if(matchlen <= 33) - { - ui32 f = ((matchlen - 2) << 2) | ((ui32)offset << 7) | 3; - fast_write(f, dst, 3); - dst += 3; - } - else - { - ui32 f = ((matchlen - 3) << 7) | ((ui32)offset << 15) | 3; - fast_write(f, dst, 4); - dst += 4; - } - } - else - { - *dst = *src; - src++; - dst++; - cword_val = (cword_val >> 1); - } + else if(matchlen <= 33) + { + ui32 f = ((matchlen - 2) << 2) | ((ui32)offset << 7) | 3; + fast_write(f, dst, 3); + dst += 3; + } + else + { + ui32 f = ((matchlen - 3) << 7) | ((ui32)offset << 15) | 3; + fast_write(f, dst, 4); + dst += 4; + } + } + else + { + *dst = *src; + src++; + dst++; + cword_val = (cword_val >> 1); + } #elif QLZ_COMPRESSION_LEVEL == 2 - if(matchlen > 2) - { - cword_val = (cword_val >> 1) | (1U << 31); - src += matchlen; + if(matchlen > 2) + { + cword_val = (cword_val >> 1) | (1U << 31); + src += matchlen; - if (matchlen < 10) - { - ui32 f = best_k | ((matchlen - 2) << 2) | (hash << 5); - fast_write(f, dst, 2); - dst += 2; - } - else - { - ui32 f = best_k | (matchlen << 16) | (hash << 5); - fast_write(f, dst, 3); - dst += 3; - } - } - else - { - *dst = *src; - src++; - dst++; - cword_val = (cword_val >> 1); - } + if (matchlen < 10) + { + ui32 f = best_k | ((matchlen - 2) << 2) | (hash << 5); + fast_write(f, dst, 2); + dst += 2; + } + else + { + ui32 f = best_k | (matchlen << 16) | (hash << 5); + fast_write(f, dst, 3); + dst += 3; + } + } + else + { + *dst = *src; + src++; + dst++; + cword_val = (cword_val >> 1); + } #endif - } + } #endif } while (src <= last_byte) @@ -520,18 +520,18 @@ static size_t qlz_compress_core(const unsigned char *source, unsigned char *dest { #if QLZ_COMPRESSION_LEVEL == 1 ui32 hash, fetch; - fetch = fast_read(src, 3); - hash = hash_func(fetch); - state->hash[hash].offset = CAST(src - OFFSET_BASE); - state->hash[hash].cache = fetch; + fetch = fast_read(src, 3); + hash = hash_func(fetch); + state->hash[hash].offset = CAST(src - OFFSET_BASE); + state->hash[hash].cache = fetch; #elif QLZ_COMPRESSION_LEVEL == 2 ui32 hash; - unsigned char c; - hash = hashat(src); - c = state->hash_counter[hash]; - state->hash[hash].offset[c & (QLZ_POINTERS - 1)] = src; - c++; - state->hash_counter[hash] = c; + unsigned char c; + hash = hashat(src); + c = state->hash_counter[hash]; + state->hash[hash].offset[c & (QLZ_POINTERS - 1)] = src; + c++; + state->hash_counter[hash] = c; #endif } #endif @@ -574,7 +574,7 @@ static size_t qlz_decompress_core(const unsigned char *source, unsigned char *de { #ifdef QLZ_MEMORY_SAFE if(src + CWORD_LEN - 1 > last_source_byte) - return 0; + return 0; #endif cword_val = fast_read(src, CWORD_LEN); src += CWORD_LEN; @@ -582,7 +582,7 @@ static size_t qlz_decompress_core(const unsigned char *source, unsigned char *de #ifdef QLZ_MEMORY_SAFE if(src + 4 - 1 > last_source_byte) - return 0; + return 0; #endif fetch = fast_read(src, 4); @@ -594,83 +594,83 @@ static size_t qlz_decompress_core(const unsigned char *source, unsigned char *de #if QLZ_COMPRESSION_LEVEL == 1 ui32 hash; - cword_val = cword_val >> 1; - hash = (fetch >> 4) & 0xfff; - offset2 = (const unsigned char *)(size_t)state->hash[hash].offset; + cword_val = cword_val >> 1; + hash = (fetch >> 4) & 0xfff; + offset2 = (const unsigned char *)(size_t)state->hash[hash].offset; - if((fetch & 0xf) != 0) - { - matchlen = (fetch & 0xf) + 2; - src += 2; - } - else - { - matchlen = *(src + 2); - src += 3; - } + if((fetch & 0xf) != 0) + { + matchlen = (fetch & 0xf) + 2; + src += 2; + } + else + { + matchlen = *(src + 2); + src += 3; + } #elif QLZ_COMPRESSION_LEVEL == 2 ui32 hash; - unsigned char c; - cword_val = cword_val >> 1; - hash = (fetch >> 5) & 0x7ff; - c = (unsigned char)(fetch & 0x3); - offset2 = state->hash[hash].offset[c]; + unsigned char c; + cword_val = cword_val >> 1; + hash = (fetch >> 5) & 0x7ff; + c = (unsigned char)(fetch & 0x3); + offset2 = state->hash[hash].offset[c]; - if((fetch & (28)) != 0) - { - matchlen = ((fetch >> 2) & 0x7) + 2; - src += 2; - } - else - { - matchlen = *(src + 2); - src += 3; - } + if((fetch & (28)) != 0) + { + matchlen = ((fetch >> 2) & 0x7) + 2; + src += 2; + } + else + { + matchlen = *(src + 2); + src += 3; + } #elif QLZ_COMPRESSION_LEVEL == 3 ui32 offset; - cword_val = cword_val >> 1; - if ((fetch & 3) == 0) - { - offset = (fetch & 0xff) >> 2; - matchlen = 3; - src++; - } - else if ((fetch & 2) == 0) - { - offset = (fetch & 0xffff) >> 2; - matchlen = 3; - src += 2; - } - else if ((fetch & 1) == 0) - { - offset = (fetch & 0xffff) >> 6; - matchlen = ((fetch >> 2) & 15) + 3; - src += 2; - } - else if ((fetch & 127) != 3) - { - offset = (fetch >> 7) & 0x1ffff; - matchlen = ((fetch >> 2) & 0x1f) + 2; - src += 3; - } - else - { - offset = (fetch >> 15); - matchlen = ((fetch >> 7) & 255) + 3; - src += 4; - } + cword_val = cword_val >> 1; + if ((fetch & 3) == 0) + { + offset = (fetch & 0xff) >> 2; + matchlen = 3; + src++; + } + else if ((fetch & 2) == 0) + { + offset = (fetch & 0xffff) >> 2; + matchlen = 3; + src += 2; + } + else if ((fetch & 1) == 0) + { + offset = (fetch & 0xffff) >> 6; + matchlen = ((fetch >> 2) & 15) + 3; + src += 2; + } + else if ((fetch & 127) != 3) + { + offset = (fetch >> 7) & 0x1ffff; + matchlen = ((fetch >> 2) & 0x1f) + 2; + src += 3; + } + else + { + offset = (fetch >> 15); + matchlen = ((fetch >> 7) & 255) + 3; + src += 4; + } - offset2 = dst - offset; + offset2 = dst - offset; #endif #ifdef QLZ_MEMORY_SAFE if(offset2 < history || offset2 > dst - MINOFFSET - 1) - return 0; + return 0; - if(matchlen > (ui32)(last_destination_byte - dst - UNCOMPRESSED_END + 1)) - return 0; + if(matchlen > (ui32)(last_destination_byte - dst - UNCOMPRESSED_END + 1)) + return 0; #endif memcpy_up(dst, offset2, matchlen); @@ -709,7 +709,7 @@ static size_t qlz_decompress_core(const unsigned char *source, unsigned char *de } #ifdef QLZ_MEMORY_SAFE if(src >= last_source_byte + 1) - return 0; + return 0; #endif *dst = *src; dst++; @@ -764,25 +764,25 @@ size_t qlz_compress(const void *source, char *destination, size_t size, qlz_stat } #if QLZ_STREAMING_BUFFER > 0 else - { - unsigned char *src = state->stream_buffer + state->stream_counter; + { + unsigned char *src = state->stream_buffer + state->stream_counter; - memcpy(src, source, size); - r = base + qlz_compress_core(src, (unsigned char*)destination + base, size, state); + memcpy(src, source, size); + r = base + qlz_compress_core(src, (unsigned char*)destination + base, size, state); - if(r == base) - { - memcpy(destination + base, src, size); - r = size + base; - compressed = 0; - reset_table_compress(state); - } - else - { - compressed = 1; - } - state->stream_counter += size; - } + if(r == base) + { + memcpy(destination + base, src, size); + r = size + base; + compressed = 0; + reset_table_compress(state); + } + else + { + compressed = 1; + } + state->stream_counter += size; + } #endif if(base == 3) { @@ -829,20 +829,20 @@ size_t qlz_decompress(const char *source, void *destination, qlz_state_decompres } #if QLZ_STREAMING_BUFFER > 0 else - { - unsigned char *dst = state->stream_buffer + state->stream_counter; - if((*source & 1) == 1) - { - dsiz = qlz_decompress_core((const unsigned char *)source, dst, dsiz, state, (const unsigned char *)state->stream_buffer); - } - else - { - memcpy(dst, source + qlz_size_header(source), dsiz); - reset_table_decompress(state); - } - memcpy(destination, dst, dsiz); - state->stream_counter += dsiz; - } + { + unsigned char *dst = state->stream_buffer + state->stream_counter; + if((*source & 1) == 1) + { + dsiz = qlz_decompress_core((const unsigned char *)source, dst, dsiz, state, (const unsigned char *)state->stream_buffer); + } + else + { + memcpy(dst, source + qlz_size_header(source), dsiz); + reset_table_decompress(state); + } + memcpy(destination, dst, dsiz); + state->stream_counter += dsiz; + } #endif return dsiz; } diff --git a/src/qlz/QuickLZ_L3.cpp b/src/qlz/QuickLZ_L3.cpp index 4f4f5ee..a9abdb7 100644 --- a/src/qlz/QuickLZ_L3.cpp +++ b/src/qlz/QuickLZ_L3.cpp @@ -27,7 +27,7 @@ #if QLZ_COMPRESSION_LEVEL == 1 && defined QLZ_PTR_64 && QLZ_STREAMING_BUFFER == 0 #define OFFSET_BASE source - #define CAST (ui32)(size_t) + #define CAST (ui32)(size_t) #else #define OFFSET_BASE 0 #define CAST @@ -56,9 +56,9 @@ int qlz_get_setting(int setting) #if QLZ_COMPRESSION_LEVEL == 1 static int same(const unsigned char *src, size_t n) { - while(n > 0 && *(src + n) == *src) - n--; - return n == 0 ? 1 : 0; + while(n > 0 && *(src + n) == *src) + n--; + return n == 0 ? 1 : 0; } #endif @@ -82,9 +82,9 @@ static void reset_table_decompress(qlz_state_decompress *state) (void)i; #if QLZ_COMPRESSION_LEVEL == 2 for(i = 0; i < QLZ_HASH_VALUES; i++) - { - state->hash_counter[i] = 0; - } + { + state->hash_counter[i] = 0; + } #endif } @@ -101,18 +101,18 @@ static __inline ui32 fast_read(void const *src, ui32 bytes) { #ifndef X86X64 unsigned char *p = (unsigned char*)src; - switch (bytes) - { - case 4: - return(*p | *(p + 1) << 8 | *(p + 2) << 16 | *(p + 3) << 24); - case 3: - return(*p | *(p + 1) << 8 | *(p + 2) << 16); - case 2: - return(*p | *(p + 1) << 8); - case 1: - return(*p); - } - return 0; + switch (bytes) + { + case 4: + return(*p | *(p + 1) << 8 | *(p + 2) << 16 | *(p + 3) << 24); + case 3: + return(*p | *(p + 1) << 8 | *(p + 2) << 16); + case 2: + return(*p | *(p + 1) << 8); + case 1: + return(*p); + } + return 0; #else if (bytes >= 1 && bytes <= 4) return *((ui32*)src); @@ -134,27 +134,27 @@ static __inline void fast_write(ui32 f, void *dst, size_t bytes) #ifndef X86X64 unsigned char *p = (unsigned char*)dst; - switch (bytes) - { - case 4: - *p = (unsigned char)f; - *(p + 1) = (unsigned char)(f >> 8); - *(p + 2) = (unsigned char)(f >> 16); - *(p + 3) = (unsigned char)(f >> 24); - return; - case 3: - *p = (unsigned char)f; - *(p + 1) = (unsigned char)(f >> 8); - *(p + 2) = (unsigned char)(f >> 16); - return; - case 2: - *p = (unsigned char)f; - *(p + 1) = (unsigned char)(f >> 8); - return; - case 1: - *p = (unsigned char)f; - return; - } + switch (bytes) + { + case 4: + *p = (unsigned char)f; + *(p + 1) = (unsigned char)(f >> 8); + *(p + 2) = (unsigned char)(f >> 16); + *(p + 3) = (unsigned char)(f >> 24); + return; + case 3: + *p = (unsigned char)f; + *(p + 1) = (unsigned char)(f >> 8); + *(p + 2) = (unsigned char)(f >> 16); + return; + case 2: + *p = (unsigned char)f; + *(p + 1) = (unsigned char)(f >> 8); + return; + case 1: + *p = (unsigned char)f; + return; + } #else switch (bytes) { @@ -199,12 +199,12 @@ static __inline void memcpy_up(unsigned char *dst, const unsigned char *src, ui3 // Caution if modifying memcpy_up! Overlap of dst and src must be special handled. #ifndef X86X64 unsigned char *end = dst + n; - while(dst < end) - { - *dst = *src; - dst++; - src++; - } + while(dst < end) + { + *dst = *src; + dst++; + src++; + } #else ui32 f = 0; do @@ -220,17 +220,17 @@ static __inline void update_hash(qlz_state_decompress *state, const unsigned cha { #if QLZ_COMPRESSION_LEVEL == 1 ui32 hash; - hash = hashat(s); - state->hash[hash].offset = s; - state->hash_counter[hash] = 1; + hash = hashat(s); + state->hash[hash].offset = s; + state->hash_counter[hash] = 1; #elif QLZ_COMPRESSION_LEVEL == 2 ui32 hash; - unsigned char c; - hash = hashat(s); - c = state->hash_counter[hash]; - state->hash[hash].offset[c & (QLZ_POINTERS - 1)] = s; - c++; - state->hash_counter[hash] = c; + unsigned char c; + hash = hashat(s); + c = state->hash_counter[hash]; + state->hash[hash].offset[c & (QLZ_POINTERS - 1)] = s; + c++; + state->hash_counter[hash] = c; #endif (void)state; (void)s; @@ -280,224 +280,224 @@ static size_t qlz_compress_core(const unsigned char *source, unsigned char *dest } #if QLZ_COMPRESSION_LEVEL == 1 { - const unsigned char *o; - ui32 hash, cached; + const unsigned char *o; + ui32 hash, cached; - hash = hash_func(fetch); - cached = fetch ^ state->hash[hash].cache; - state->hash[hash].cache = fetch; + hash = hash_func(fetch); + cached = fetch ^ state->hash[hash].cache; + state->hash[hash].cache = fetch; - o = state->hash[hash].offset + OFFSET_BASE; - state->hash[hash].offset = CAST(src - OFFSET_BASE); + o = state->hash[hash].offset + OFFSET_BASE; + state->hash[hash].offset = CAST(src - OFFSET_BASE); #ifdef X86X64 - if ((cached & 0xffffff) == 0 && o != OFFSET_BASE && (src - o > MINOFFSET || (src == o + 1 && lits >= 3 && src > source + 3 && same(src - 3, 6)))) - { - if(cached != 0) - { + if ((cached & 0xffffff) == 0 && o != OFFSET_BASE && (src - o > MINOFFSET || (src == o + 1 && lits >= 3 && src > source + 3 && same(src - 3, 6)))) + { + if(cached != 0) + { #else - if (cached == 0 && o != OFFSET_BASE && (src - o > MINOFFSET || (src == o + 1 && lits >= 3 && src > source + 3 && same(src - 3, 6)))) - { - if (*(o + 3) != *(src + 3)) - { + if (cached == 0 && o != OFFSET_BASE && (src - o > MINOFFSET || (src == o + 1 && lits >= 3 && src > source + 3 && same(src - 3, 6)))) + { + if (*(o + 3) != *(src + 3)) + { #endif - hash <<= 4; - cword_val = (cword_val >> 1) | (1U << 31); - fast_write((3 - 2) | hash, dst, 2); - src += 3; - dst += 2; - } - else - { - const unsigned char *old_src = src; - size_t matchlen; - hash <<= 4; + hash <<= 4; + cword_val = (cword_val >> 1) | (1U << 31); + fast_write((3 - 2) | hash, dst, 2); + src += 3; + dst += 2; + } + else + { + const unsigned char *old_src = src; + size_t matchlen; + hash <<= 4; - cword_val = (cword_val >> 1) | (1U << 31); - src += 4; + cword_val = (cword_val >> 1) | (1U << 31); + src += 4; - if(*(o + (src - old_src)) == *src) - { - src++; - if(*(o + (src - old_src)) == *src) - { - size_t q = last_byte - UNCOMPRESSED_END - (src - 5) + 1; - size_t remaining = q > 255 ? 255 : q; - src++; - while(*(o + (src - old_src)) == *src && (size_t)(src - old_src) < remaining) - src++; - } - } + if(*(o + (src - old_src)) == *src) + { + src++; + if(*(o + (src - old_src)) == *src) + { + size_t q = last_byte - UNCOMPRESSED_END - (src - 5) + 1; + size_t remaining = q > 255 ? 255 : q; + src++; + while(*(o + (src - old_src)) == *src && (size_t)(src - old_src) < remaining) + src++; + } + } - matchlen = src - old_src; - if (matchlen < 18) - { - fast_write((ui32)(matchlen - 2) | hash, dst, 2); - dst += 2; - } - else - { - fast_write((ui32)(matchlen << 16) | hash, dst, 3); - dst += 3; - } - } - fetch = fast_read(src, 3); - lits = 0; - } - else - { - lits++; - *dst = *src; - src++; - dst++; - cword_val = (cword_val >> 1); + matchlen = src - old_src; + if (matchlen < 18) + { + fast_write((ui32)(matchlen - 2) | hash, dst, 2); + dst += 2; + } + else + { + fast_write((ui32)(matchlen << 16) | hash, dst, 3); + dst += 3; + } + } + fetch = fast_read(src, 3); + lits = 0; + } + else + { + lits++; + *dst = *src; + src++; + dst++; + cword_val = (cword_val >> 1); #ifdef X86X64 - fetch = fast_read(src, 3); + fetch = fast_read(src, 3); #else - fetch = (fetch >> 8 & 0xffff) | (*(src + 2) << 16); + fetch = (fetch >> 8 & 0xffff) | (*(src + 2) << 16); #endif - } - } + } + } #elif QLZ_COMPRESSION_LEVEL >= 2 { - const unsigned char *o, *offset2; - ui32 hash, matchlen, k, m, best_k = 0; - unsigned char c; - size_t remaining = (last_byte - UNCOMPRESSED_END - src + 1) > 255 ? 255 : (last_byte - UNCOMPRESSED_END - src + 1); - (void)best_k; + const unsigned char *o, *offset2; + ui32 hash, matchlen, k, m, best_k = 0; + unsigned char c; + size_t remaining = (last_byte - UNCOMPRESSED_END - src + 1) > 255 ? 255 : (last_byte - UNCOMPRESSED_END - src + 1); + (void)best_k; - //hash = hashat(src); - fetch = fast_read(src, 3); - hash = hash_func(fetch); + //hash = hashat(src); + fetch = fast_read(src, 3); + hash = hash_func(fetch); - c = state->hash_counter[hash]; + c = state->hash_counter[hash]; - offset2 = state->hash[hash].offset[0]; - if(offset2 < src - MINOFFSET && c > 0 && ((fast_read(offset2, 3) ^ fetch) & 0xffffff) == 0) - { - matchlen = 3; - if(*(offset2 + matchlen) == *(src + matchlen)) - { - matchlen = 4; - while(*(offset2 + matchlen) == *(src + matchlen) && matchlen < remaining) - matchlen++; - } - } - else - matchlen = 0; - for(k = 1; k < QLZ_POINTERS && c > k; k++) - { - o = state->hash[hash].offset[k]; + offset2 = state->hash[hash].offset[0]; + if(offset2 < src - MINOFFSET && c > 0 && ((fast_read(offset2, 3) ^ fetch) & 0xffffff) == 0) + { + matchlen = 3; + if(*(offset2 + matchlen) == *(src + matchlen)) + { + matchlen = 4; + while(*(offset2 + matchlen) == *(src + matchlen) && matchlen < remaining) + matchlen++; + } + } + else + matchlen = 0; + for(k = 1; k < QLZ_POINTERS && c > k; k++) + { + o = state->hash[hash].offset[k]; #if QLZ_COMPRESSION_LEVEL == 3 - if(((fast_read(o, 3) ^ fetch) & 0xffffff) == 0 && o < src - MINOFFSET) + if(((fast_read(o, 3) ^ fetch) & 0xffffff) == 0 && o < src - MINOFFSET) #elif QLZ_COMPRESSION_LEVEL == 2 - if(*(src + matchlen) == *(o + matchlen) && ((fast_read(o, 3) ^ fetch) & 0xffffff) == 0 && o < src - MINOFFSET) + if(*(src + matchlen) == *(o + matchlen) && ((fast_read(o, 3) ^ fetch) & 0xffffff) == 0 && o < src - MINOFFSET) #endif - { - m = 3; - while(*(o + m) == *(src + m) && m < remaining) - m++; + { + m = 3; + while(*(o + m) == *(src + m) && m < remaining) + m++; #if QLZ_COMPRESSION_LEVEL == 3 - if ((m > matchlen) || (m == matchlen && o > offset2)) + if ((m > matchlen) || (m == matchlen && o > offset2)) #elif QLZ_COMPRESSION_LEVEL == 2 - if (m > matchlen) + if (m > matchlen) #endif - { - offset2 = o; - matchlen = m; - best_k = k; - } - } - } - o = offset2; - state->hash[hash].offset[c & (QLZ_POINTERS - 1)] = src; - c++; - state->hash_counter[hash] = c; + { + offset2 = o; + matchlen = m; + best_k = k; + } + } + } + o = offset2; + state->hash[hash].offset[c & (QLZ_POINTERS - 1)] = src; + c++; + state->hash_counter[hash] = c; #if QLZ_COMPRESSION_LEVEL == 3 - if(matchlen > 2 && src - o < 131071) - { - ui32 u; - size_t offset = src - o; + if(matchlen > 2 && src - o < 131071) + { + ui32 u; + size_t offset = src - o; - for(u = 1; u < matchlen; u++) - { - hash = hashat(src + u); - c = state->hash_counter[hash]++; - state->hash[hash].offset[c & (QLZ_POINTERS - 1)] = src + u; - } + for(u = 1; u < matchlen; u++) + { + hash = hashat(src + u); + c = state->hash_counter[hash]++; + state->hash[hash].offset[c & (QLZ_POINTERS - 1)] = src + u; + } - cword_val = (cword_val >> 1) | (1U << 31); - src += matchlen; + cword_val = (cword_val >> 1) | (1U << 31); + src += matchlen; - if(matchlen == 3 && offset <= 63) - { - *dst = (unsigned char)(offset << 2); - dst++; - } - else if (matchlen == 3 && offset <= 16383) - { - ui32 f = (ui32)((offset << 2) | 1); - fast_write(f, dst, 2); - dst += 2; - } - else if (matchlen <= 18 && offset <= 1023) - { - ui32 f = ((matchlen - 3) << 2) | ((ui32)offset << 6) | 2; - fast_write(f, dst, 2); - dst += 2; - } + if(matchlen == 3 && offset <= 63) + { + *dst = (unsigned char)(offset << 2); + dst++; + } + else if (matchlen == 3 && offset <= 16383) + { + ui32 f = (ui32)((offset << 2) | 1); + fast_write(f, dst, 2); + dst += 2; + } + else if (matchlen <= 18 && offset <= 1023) + { + ui32 f = ((matchlen - 3) << 2) | ((ui32)offset << 6) | 2; + fast_write(f, dst, 2); + dst += 2; + } - else if(matchlen <= 33) - { - ui32 f = ((matchlen - 2) << 2) | ((ui32)offset << 7) | 3; - fast_write(f, dst, 3); - dst += 3; - } - else - { - ui32 f = ((matchlen - 3) << 7) | ((ui32)offset << 15) | 3; - fast_write(f, dst, 4); - dst += 4; - } - } - else - { - *dst = *src; - src++; - dst++; - cword_val = (cword_val >> 1); - } + else if(matchlen <= 33) + { + ui32 f = ((matchlen - 2) << 2) | ((ui32)offset << 7) | 3; + fast_write(f, dst, 3); + dst += 3; + } + else + { + ui32 f = ((matchlen - 3) << 7) | ((ui32)offset << 15) | 3; + fast_write(f, dst, 4); + dst += 4; + } + } + else + { + *dst = *src; + src++; + dst++; + cword_val = (cword_val >> 1); + } #elif QLZ_COMPRESSION_LEVEL == 2 - if(matchlen > 2) - { - cword_val = (cword_val >> 1) | (1U << 31); - src += matchlen; + if(matchlen > 2) + { + cword_val = (cword_val >> 1) | (1U << 31); + src += matchlen; - if (matchlen < 10) - { - ui32 f = best_k | ((matchlen - 2) << 2) | (hash << 5); - fast_write(f, dst, 2); - dst += 2; - } - else - { - ui32 f = best_k | (matchlen << 16) | (hash << 5); - fast_write(f, dst, 3); - dst += 3; - } - } - else - { - *dst = *src; - src++; - dst++; - cword_val = (cword_val >> 1); - } + if (matchlen < 10) + { + ui32 f = best_k | ((matchlen - 2) << 2) | (hash << 5); + fast_write(f, dst, 2); + dst += 2; + } + else + { + ui32 f = best_k | (matchlen << 16) | (hash << 5); + fast_write(f, dst, 3); + dst += 3; + } + } + else + { + *dst = *src; + src++; + dst++; + cword_val = (cword_val >> 1); + } #endif - } + } #endif } while (src <= last_byte) @@ -514,18 +514,18 @@ static size_t qlz_compress_core(const unsigned char *source, unsigned char *dest { #if QLZ_COMPRESSION_LEVEL == 1 ui32 hash, fetch; - fetch = fast_read(src, 3); - hash = hash_func(fetch); - state->hash[hash].offset = CAST(src - OFFSET_BASE); - state->hash[hash].cache = fetch; + fetch = fast_read(src, 3); + hash = hash_func(fetch); + state->hash[hash].offset = CAST(src - OFFSET_BASE); + state->hash[hash].cache = fetch; #elif QLZ_COMPRESSION_LEVEL == 2 ui32 hash; - unsigned char c; - hash = hashat(src); - c = state->hash_counter[hash]; - state->hash[hash].offset[c & (QLZ_POINTERS - 1)] = src; - c++; - state->hash_counter[hash] = c; + unsigned char c; + hash = hashat(src); + c = state->hash_counter[hash]; + state->hash[hash].offset[c & (QLZ_POINTERS - 1)] = src; + c++; + state->hash_counter[hash] = c; #endif } #endif @@ -569,7 +569,7 @@ static size_t qlz_decompress_core(const unsigned char *source, unsigned char *de { #ifdef QLZ_MEMORY_SAFE if(src + CWORD_LEN - 1 > last_source_byte) - return 0; + return 0; #endif cword_val = fast_read(src, CWORD_LEN); src += CWORD_LEN; @@ -577,7 +577,7 @@ static size_t qlz_decompress_core(const unsigned char *source, unsigned char *de #ifdef QLZ_MEMORY_SAFE if(src + 4 - 1 > last_source_byte) - return 0; + return 0; #endif fetch = fast_read(src, 4); @@ -589,83 +589,83 @@ static size_t qlz_decompress_core(const unsigned char *source, unsigned char *de #if QLZ_COMPRESSION_LEVEL == 1 ui32 hash; - cword_val = cword_val >> 1; - hash = (fetch >> 4) & 0xfff; - offset2 = (const unsigned char *)(size_t)state->hash[hash].offset; + cword_val = cword_val >> 1; + hash = (fetch >> 4) & 0xfff; + offset2 = (const unsigned char *)(size_t)state->hash[hash].offset; - if((fetch & 0xf) != 0) - { - matchlen = (fetch & 0xf) + 2; - src += 2; - } - else - { - matchlen = *(src + 2); - src += 3; - } + if((fetch & 0xf) != 0) + { + matchlen = (fetch & 0xf) + 2; + src += 2; + } + else + { + matchlen = *(src + 2); + src += 3; + } #elif QLZ_COMPRESSION_LEVEL == 2 ui32 hash; - unsigned char c; - cword_val = cword_val >> 1; - hash = (fetch >> 5) & 0x7ff; - c = (unsigned char)(fetch & 0x3); - offset2 = state->hash[hash].offset[c]; + unsigned char c; + cword_val = cword_val >> 1; + hash = (fetch >> 5) & 0x7ff; + c = (unsigned char)(fetch & 0x3); + offset2 = state->hash[hash].offset[c]; - if((fetch & (28)) != 0) - { - matchlen = ((fetch >> 2) & 0x7) + 2; - src += 2; - } - else - { - matchlen = *(src + 2); - src += 3; - } + if((fetch & (28)) != 0) + { + matchlen = ((fetch >> 2) & 0x7) + 2; + src += 2; + } + else + { + matchlen = *(src + 2); + src += 3; + } #elif QLZ_COMPRESSION_LEVEL == 3 ui32 offset; - cword_val = cword_val >> 1; - if ((fetch & 3) == 0) - { - offset = (fetch & 0xff) >> 2; - matchlen = 3; - src++; - } - else if ((fetch & 2) == 0) - { - offset = (fetch & 0xffff) >> 2; - matchlen = 3; - src += 2; - } - else if ((fetch & 1) == 0) - { - offset = (fetch & 0xffff) >> 6; - matchlen = ((fetch >> 2) & 15) + 3; - src += 2; - } - else if ((fetch & 127) != 3) - { - offset = (fetch >> 7) & 0x1ffff; - matchlen = ((fetch >> 2) & 0x1f) + 2; - src += 3; - } - else - { - offset = (fetch >> 15); - matchlen = ((fetch >> 7) & 255) + 3; - src += 4; - } + cword_val = cword_val >> 1; + if ((fetch & 3) == 0) + { + offset = (fetch & 0xff) >> 2; + matchlen = 3; + src++; + } + else if ((fetch & 2) == 0) + { + offset = (fetch & 0xffff) >> 2; + matchlen = 3; + src += 2; + } + else if ((fetch & 1) == 0) + { + offset = (fetch & 0xffff) >> 6; + matchlen = ((fetch >> 2) & 15) + 3; + src += 2; + } + else if ((fetch & 127) != 3) + { + offset = (fetch >> 7) & 0x1ffff; + matchlen = ((fetch >> 2) & 0x1f) + 2; + src += 3; + } + else + { + offset = (fetch >> 15); + matchlen = ((fetch >> 7) & 255) + 3; + src += 4; + } - offset2 = dst - offset; + offset2 = dst - offset; #endif #ifdef QLZ_MEMORY_SAFE if(offset2 < history || offset2 > dst - MINOFFSET - 1) - return 0; + return 0; - if(matchlen > (ui32)(last_destination_byte - dst - UNCOMPRESSED_END + 1)) - return 0; + if(matchlen > (ui32)(last_destination_byte - dst - UNCOMPRESSED_END + 1)) + return 0; #endif memcpy_up(dst, offset2, matchlen); @@ -704,7 +704,7 @@ static size_t qlz_decompress_core(const unsigned char *source, unsigned char *de } #ifdef QLZ_MEMORY_SAFE if(src >= last_source_byte + 1) - return 0; + return 0; #endif *dst = *src; dst++; @@ -759,25 +759,25 @@ size_t qlz_compress(const void *source, char *destination, size_t size, qlz_stat } #if QLZ_STREAMING_BUFFER > 0 else - { - unsigned char *src = state->stream_buffer + state->stream_counter; + { + unsigned char *src = state->stream_buffer + state->stream_counter; - memcpy(src, source, size); - r = base + qlz_compress_core(src, (unsigned char*)destination + base, size, state); + memcpy(src, source, size); + r = base + qlz_compress_core(src, (unsigned char*)destination + base, size, state); - if(r == base) - { - memcpy(destination + base, src, size); - r = size + base; - compressed = 0; - reset_table_compress(state); - } - else - { - compressed = 1; - } - state->stream_counter += size; - } + if(r == base) + { + memcpy(destination + base, src, size); + r = size + base; + compressed = 0; + reset_table_compress(state); + } + else + { + compressed = 1; + } + state->stream_counter += size; + } #endif if(base == 3) { @@ -824,20 +824,20 @@ size_t qlz_decompress(const char *source, void *destination, qlz_state_decompres } #if QLZ_STREAMING_BUFFER > 0 else - { - unsigned char *dst = state->stream_buffer + state->stream_counter; - if((*source & 1) == 1) - { - dsiz = qlz_decompress_core((const unsigned char *)source, dst, dsiz, state, (const unsigned char *)state->stream_buffer); - } - else - { - memcpy(dst, source + qlz_size_header(source), dsiz); - reset_table_decompress(state); - } - memcpy(destination, dst, dsiz); - state->stream_counter += dsiz; - } + { + unsigned char *dst = state->stream_buffer + state->stream_counter; + if((*source & 1) == 1) + { + dsiz = qlz_decompress_core((const unsigned char *)source, dst, dsiz, state, (const unsigned char *)state->stream_buffer); + } + else + { + memcpy(dst, source + qlz_size_header(source), dsiz); + reset_table_decompress(state); + } + memcpy(destination, dst, dsiz); + state->stream_counter += dsiz; + } #endif return dsiz; } diff --git a/src/query/Command.h b/src/query/Command.h index 5b1fe7d..0cf6c88 100644 --- a/src/query/Command.h +++ b/src/query/Command.h @@ -1,9 +1,9 @@ #pragma once #ifdef byte - #define byte asdd + #define byte asdd #ifndef WIN32 - #warning The byte macro is already defined! Undefining it! + #warning The byte macro is already defined! Undefining it! #endif #undef byte #endif @@ -35,182 +35,182 @@ operator type(){ \ fromString; \ } - class Command; - class ValueList; + class Command; + 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 { - friend class Command; - friend class ValueList; - public: - ParameterBulk(const ParameterBulk& ref) : parms(ref.parms) {} + class ParameterBulk { + friend class Command; + friend class ValueList; + public: + ParameterBulk(const ParameterBulk& ref) : parms(ref.parms) {} - variable operator[](size_t index){ - if(parms.size() > index) return parms[index]; - return variable{"", "", VARTYPE_NULL}; - } + variable operator[](size_t index){ + if(parms.size() > index) return parms[index]; + return variable{"", "", VARTYPE_NULL}; + } - const variable& operator[](const std::string& key) const { - for(const auto& elm : parms) - if(elm.key() == key){ - return elm; - } + const variable& operator[](const std::string& key) const { + for(const auto& elm : parms) + if(elm.key() == key){ + 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) { - for(auto& elm : parms) - if(elm.key() == key){ - return elm; - } - this->parms.push_back(variable(key, "", VariableType::VARTYPE_NULL)); - return this->operator[](key); - } + variable& operator[](const std::string& key) { + for(auto& elm : parms) + if(elm.key() == key){ + return elm; + } + this->parms.push_back(variable(key, "", VariableType::VARTYPE_NULL)); + return this->operator[](key); + } - bool has(const std::string& key) const { - for(const auto& elm : parms) - if(elm.key() == key && elm.type() != VariableType::VARTYPE_NULL) return true; - return false; - } + bool has(const std::string& key) const { + for(const auto& elm : parms) + if(elm.key() == key && elm.type() != VariableType::VARTYPE_NULL) return true; + return false; + } - std::deque keys() const { - std::deque result; - for(const auto& elm : parms) - result.push_back(elm.key()); - return result; - } + std::deque keys() const { + std::deque result; + for(const auto& elm : parms) + result.push_back(elm.key()); + return result; + } - ParameterBulk& operator=(const ParameterBulk& ref){ - parms = ref.parms; - return *this; - } - private: - ParameterBulk() {} - ParameterBulk(std::deque p) : parms(p) {} - std::deque parms; - }; + ParameterBulk& operator=(const ParameterBulk& ref){ + parms = ref.parms; + return *this; + } + private: + ParameterBulk() {} + ParameterBulk(std::deque p) : parms(p) {} + std::deque parms; + }; - class ValueList { - friend class Command; - public: - ValueList() = delete; - ValueList(const ValueList& ref) : key(ref.key), bulkList(ref.bulkList) {} + class ValueList { + friend class Command; + public: + ValueList() = delete; + ValueList(const ValueList& ref) : key(ref.key), bulkList(ref.bulkList) {} - variable operator[](int index){ - while(index >= bulkList.size()) bulkList.push_back(ParameterBulk()); - return bulkList[index][key]; - } + variable operator[](int index){ + while(index >= bulkList.size()) bulkList.push_back(ParameterBulk()); + return bulkList[index][key]; + } - variable first() const { - int index = 0; - while(index < bulkList.size() && !bulkList[index].has(key)) index++; - if(index < bulkList.size()) return bulkList[index][key]; + variable first() const { + int index = 0; + while(index < bulkList.size() && !bulkList[index].has(key)) index++; + if(index < bulkList.size()) return bulkList[index][key]; - return variable{this->key, "", VariableType::VARTYPE_NULL}; - throw std::invalid_argument("could not find key [" + key + "]"); - } + return variable{this->key, "", VariableType::VARTYPE_NULL}; + throw std::invalid_argument("could not find key [" + key + "]"); + } - size_t size(){ - size_t count = 0; - for(const auto& blk : this->bulkList) - if(blk.has(this->key)) count++; - return count; - } + size_t size(){ + size_t count = 0; + for(const auto& blk : this->bulkList) + if(blk.has(this->key)) count++; + return count; + } - template - ValueList& operator=(T var){ operator[](0) = var; return *this; } - ValueList& operator=(ts::ValueList& var){ operator[](0) = var.first().value(); return *this; } + template + ValueList& operator=(T var){ operator[](0) = var; return *this; } + ValueList& operator=(ts::ValueList& var){ operator[](0) = var.first().value(); return *this; } - template - T as() const { return first().as(); } + template + T as() const { return first().as(); } - template - operator T() { return as(); } + template + operator T() { return as(); } - template - bool operator==(T other){ return as() == other; } - template - bool operator!=(T other){ return as() != other; } + template + bool operator==(T other){ return as() == other; } + template + bool operator!=(T other){ return as() != other; } - std::string string() const { return as(); } + std::string string() const { return as(); } - friend std::ostream& operator<<(std::ostream&, const ValueList&); - private: - ValueList(std::string& key, std::deque& bulkList) : key(key), bulkList(bulkList) {} - std::string key; - public: - std::deque& bulkList; - }; + friend std::ostream& operator<<(std::ostream&, const ValueList&); + private: + ValueList(std::string& key, std::deque& bulkList) : key(key), bulkList(bulkList) {} + std::string key; + public: + std::deque& bulkList; + }; - inline std::ostream& operator<<(std::ostream& stream,const ValueList& list) { - stream << "{ Key: " << list.key << " = ["; - for(auto it = list.bulkList.begin(); it != list.bulkList.end(); it++) - if(it->has(list.key)) { - stream << (*it)[list.key].value(); - if(it + 1 != list.bulkList.end()) - stream << ", "; - } - stream << "]}"; - return stream; - } + inline std::ostream& operator<<(std::ostream& stream,const ValueList& list) { + stream << "{ Key: " << list.key << " = ["; + for(auto it = list.bulkList.begin(); it != list.bulkList.end(); it++) + if(it->has(list.key)) { + stream << (*it)[list.key].value(); + if(it + 1 != list.bulkList.end()) + stream << ", "; + } + stream << "]}"; + return stream; + } - class Command { - public: - static Command parse(const pipes::buffer_view& buffer, bool expect_command = true, bool drop_non_utf8 = false); + class Command { + public: + 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, std::initializer_list); - explicit Command(const std::string& command, std::initializer_list>); + explicit Command(const std::string& command); + explicit Command(const std::string& command, std::initializer_list); + explicit Command(const std::string& command, std::initializer_list>); - Command(const Command&); - ~Command(); + Command(const Command&); + ~Command(); - inline std::string command() const { return getCommand(); } - std::string getCommand() const { return _command; } + inline std::string command() const { return getCommand(); } + std::string getCommand() const { return _command; } - std::string build(bool escaped = true) const; + std::string build(bool escaped = true) const; #ifdef HAVE_JSON - Json::Value buildJson() const; + Json::Value buildJson() const; #endif - const ParameterBulk& operator[](size_t index) const { - if(bulks.size() <= index) throw std::invalid_argument("got out of length"); - return bulks[index]; - } + const ParameterBulk& operator[](size_t index) const { + if(bulks.size() <= index) throw std::invalid_argument("got out of length"); + return bulks[index]; + } - ParameterBulk& operator[](size_t index){ - while(bulks.size() <= index) bulks.push_back(ParameterBulk{}); - return bulks[index]; - } + ParameterBulk& operator[](size_t index){ + while(bulks.size() <= index) bulks.push_back(ParameterBulk{}); + return bulks[index]; + } - ValueList operator[](std::string key){ - return ValueList(key, bulks); - } + ValueList operator[](std::string key){ + return ValueList(key, bulks); + } - size_t bulkCount() const { return bulks.size(); } - void pop_bulk(); - void push_bulk_front(); + size_t bulkCount() const { return bulks.size(); } + void pop_bulk(); + void push_bulk_front(); - bool hasParm(std::string); - std::deque parms(); - void enableParm(const std::string& key){ toggleParm(key, true); } - void disableParm(const std::string& key){ toggleParm(key, false); } - void toggleParm(const std::string& key, bool flag); + bool hasParm(std::string); + std::deque parms(); + void enableParm(const std::string& key){ toggleParm(key, true); } + void disableParm(const std::string& key){ toggleParm(key, false); } + void toggleParm(const std::string& key, bool flag); - void reverseBulks(); - private: - Command(); + void reverseBulks(); + private: + Command(); - std::string _command; - std::deque bulks; - std::deque paramethers; - }; + std::string _command; + std::deque bulks; + std::deque paramethers; + }; } DEFINE_VARIABLE_TRANSFORM_TO_STR(ts::ValueList, in.string()); diff --git a/src/query/command2.cpp b/src/query/command2.cpp index 41bb821..3ea7c9f 100644 --- a/src/query/command2.cpp +++ b/src/query/command2.cpp @@ -8,16 +8,16 @@ using namespace ts; #define CONVERTER_ST(type, m_decode, m_encode) \ CONVERTER_METHOD_DECODE(type, impl::converter_ ##type ##_decode) { \ - m_decode; \ + m_decode; \ } \ \ CONVERTER_METHOD_ENCODE(type, impl::converter_ ##type ##_encode) { \ - m_encode \ + m_encode \ } #define CONVERTER_PRIMITIVE_ST(type, m_decode) CONVERTER_ST(type, \ - return m_decode;, \ - return std::to_string(std::any_cast(value)); \ + return m_decode;, \ + return std::to_string(std::any_cast(value)); \ ) CONVERTER_PRIMITIVE_ST(int8_t, std::stol(str) & 0xFF); @@ -41,214 +41,214 @@ CONVERTER_ST(std__string, return str;, return std::any_cast(value); CONVERTER_ST(const_char__ , return str.c_str();, return std::string(std::any_cast(value));); command::command(const std::string& command, bool editable) { - this->handle = make_shared(); - this->handle->editable = editable; - this->handle->command = command; + this->handle = make_shared(); + this->handle->editable = editable; + this->handle->command = command; } std::string command::identifier() const { - return this->handle->command; + return this->handle->command; } void command::set_identifier(const std::string &command) { - this->handle->command = command; + this->handle->command = command; } command_bulk command::bulk(size_t index) { - if(this->handle->bulks.size() <= index) { - if(!this->handle->editable) - throw command_bulk_exceed_index_exception(); + if(this->handle->bulks.size() <= index) { + if(!this->handle->editable) + throw command_bulk_exceed_index_exception(); - while(this->handle->bulks.size() <= index) { - auto bulk = make_shared(); - bulk->handle = this->handle.get(); - this->handle->bulks.push_back(std::move(bulk)); - } - } + while(this->handle->bulks.size() <= index) { + auto bulk = make_shared(); + bulk->handle = this->handle.get(); + this->handle->bulks.push_back(std::move(bulk)); + } + } - return {index, this->handle->bulks[index]}; + return {index, this->handle->bulks[index]}; } const command_bulk command::bulk(size_t index) const { - if(this->handle->bulks.size() <= index) - throw command_bulk_exceed_index_exception(); + if(this->handle->bulks.size() <= index) + throw command_bulk_exceed_index_exception(); - return {index, this->handle->bulks[index]}; + return {index, this->handle->bulks[index]}; } size_t command::bulk_count() const { - return this->handle->bulks.size(); + return this->handle->bulks.size(); } command_entry command::value(const std::string &key) { - return this->bulk(0)[key]; + return this->bulk(0)[key]; } const command_entry command::value(const std::string &key) const { - return this->bulk(0)[key]; + return this->bulk(0)[key]; } bool command::has_value(const std::string &key) const { - if(this->bulk_count() == 0) return false; + if(this->bulk_count() == 0) return false; - return this->bulk(0).has(key); + return this->bulk(0).has(key); } bool command::has_trigger(const std::string &key) const { - for(const auto& trigger : this->handle->triggers) - if(trigger == key) - return true; - return false; + for(const auto& trigger : this->handle->triggers) + if(trigger == key) + return true; + return false; } void command::set_trigger(const std::string &key, bool value) { - auto& triggers = this->handle->triggers; - auto it = find(triggers.begin(), triggers.end(), key); - if(it == triggers.end() && value) { - triggers.push_back(key); - } else if(it != triggers.end() && !value) { - triggers.erase(it); - } + auto& triggers = this->handle->triggers; + auto it = find(triggers.begin(), triggers.end(), key); + if(it == triggers.end() && value) { + triggers.push_back(key); + } else if(it != triggers.end() && !value) { + triggers.erase(it); + } } command command::parse(const std::string_view &data, bool expect_type, bool drop_non_utf8) { - command result; + command result; - size_t current_index = std::string::npos, end_index; - if(expect_type) { - current_index = data.find(' ', 0); - if(current_index == std::string::npos){ - result.set_identifier(std::string(data)); - return result; - } else { - result.set_identifier(std::string(data.substr(0, current_index))); - } - } + size_t current_index = std::string::npos, end_index; + if(expect_type) { + current_index = data.find(' ', 0); + if(current_index == std::string::npos){ + result.set_identifier(std::string(data)); + return result; + } else { + result.set_identifier(std::string(data.substr(0, current_index))); + } + } - size_t bulk_index = 0; - while(++current_index > 0 || (current_index == 0 && !expect_type && (expect_type = true))) { - end_index = data.find_first_of(" |", current_index); + size_t bulk_index = 0; + while(++current_index > 0 || (current_index == 0 && !expect_type && (expect_type = true))) { + end_index = data.find_first_of(" |", current_index); - if(end_index != current_index) { /* else we've found another space or a pipe */ - if(data[current_index] == '-') { - string trigger(data.substr(current_index + 1, end_index - current_index - 1)); - result.set_trigger(trigger); - } else { - auto index_assign = data.find_first_of('=', current_index); - string key, value; - if(index_assign == string::npos || index_assign > end_index) { - key = data.substr(current_index, end_index - current_index); - } else { - key = data.substr(current_index, index_assign - current_index); - try { - value = query::unescape(string(data.substr(index_assign + 1, end_index - index_assign - 1)), true); - } catch(const std::invalid_argument& ex) { + if(end_index != current_index) { /* else we've found another space or a pipe */ + if(data[current_index] == '-') { + string trigger(data.substr(current_index + 1, end_index - current_index - 1)); + result.set_trigger(trigger); + } else { + auto index_assign = data.find_first_of('=', current_index); + string key, value; + if(index_assign == string::npos || index_assign > end_index) { + key = data.substr(current_index, end_index - current_index); + } else { + key = data.substr(current_index, index_assign - current_index); + try { + value = query::unescape(string(data.substr(index_assign + 1, end_index - index_assign - 1)), true); + } catch(const std::invalid_argument& ex) { (void) ex; - /* invalid character at index X */ - if(!drop_non_utf8) - throw; + /* invalid character at index X */ + if(!drop_non_utf8) + throw; - goto skip_assign; - } - } + goto skip_assign; + } + } - { - const static auto key_validator = [](char c){ return !((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_' || c == '-'); }; - auto invalid_index = find_if(key.begin(), key.end(), key_validator); - if(invalid_index != key.end()) - throw command_malformed_exception(current_index + distance(key.begin(), invalid_index)); + { + const static auto key_validator = [](char c){ return !((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_' || c == '-'); }; + auto invalid_index = find_if(key.begin(), key.end(), key_validator); + if(invalid_index != key.end()) + throw command_malformed_exception(current_index + distance(key.begin(), invalid_index)); - if(!key.empty() && !result[bulk_index].has(key)) - result[bulk_index][key] = value; - } + if(!key.empty() && !result[bulk_index].has(key)) + result[bulk_index][key] = value; + } - skip_assign:; - } - } + skip_assign:; + } + } - if(end_index < data.length() && data[end_index] == '|') - bulk_index++; - current_index = end_index; - } + if(end_index < data.length() && data[end_index] == '|') + bulk_index++; + current_index = end_index; + } - return result; + return result; } std::string command::build(ts::command::format::value type) { - if(type == format::QUERY || type == format::BRACE_ESCAPED_QUERY) { - std::stringstream ss; + if(type == format::QUERY || type == format::BRACE_ESCAPED_QUERY) { + std::stringstream ss; - if(!this->handle->command.empty()) - ss << this->handle->command << " "; + if(!this->handle->command.empty()) + ss << this->handle->command << " "; - if(!this->handle->bulks.empty()) { - auto max_bulk_index = this->handle->bulks.size() - 1; - for(size_t bulk_index = 0; bulk_index <= max_bulk_index; bulk_index++) { - auto& bulk = this->handle->bulks[bulk_index]; - if(bulk->values.empty()) continue; //Do not remove me! + if(!this->handle->bulks.empty()) { + auto max_bulk_index = this->handle->bulks.size() - 1; + for(size_t bulk_index = 0; bulk_index <= max_bulk_index; bulk_index++) { + auto& bulk = this->handle->bulks[bulk_index]; + if(bulk->values.empty()) continue; //Do not remove me! - auto max_pair_index = bulk->values.size() - 1; - auto pair_it = bulk->values.begin(); + auto max_pair_index = bulk->values.size() - 1; + auto pair_it = bulk->values.begin(); - for(size_t pair_index = 0; pair_index <= max_pair_index; pair_index++) { - auto pair = *(pair_it++); + for(size_t pair_index = 0; pair_index <= max_pair_index; pair_index++) { + auto pair = *(pair_it++); - auto value = pair.second->casted ? pair.second->to_string(pair.second->value) : pair.second->value.has_value() ? any_cast(pair.second->value) : ""; - ss << pair.first << "="; - if(type == format::BRACE_ESCAPED_QUERY) { - ss << "\"" << value << "\""; - } else ss << query::escape(value); + auto value = pair.second->casted ? pair.second->to_string(pair.second->value) : pair.second->value.has_value() ? any_cast(pair.second->value) : ""; + ss << pair.first << "="; + if(type == format::BRACE_ESCAPED_QUERY) { + ss << "\"" << value << "\""; + } else ss << query::escape(value); - if(pair_index != max_pair_index) - ss << " "; - } + if(pair_index != max_pair_index) + ss << " "; + } - if(bulk_index != max_bulk_index) - ss << " | "; - } - } + if(bulk_index != max_bulk_index) + ss << " | "; + } + } - if(!this->handle->triggers.empty()) { - auto max_trigger_index = this->handle->triggers.size() - 1; - for(size_t trigger_index = 0; trigger_index <= max_trigger_index; trigger_index++) { - ss << " -" << this->handle->triggers[trigger_index]; - } - } + if(!this->handle->triggers.empty()) { + auto max_trigger_index = this->handle->triggers.size() - 1; + for(size_t trigger_index = 0; trigger_index <= max_trigger_index; trigger_index++) { + ss << " -" << this->handle->triggers[trigger_index]; + } + } - return ss.str(); - } - return ""; + return ss.str(); + } + return ""; } bool command_bulk::has(const std::string &key) const { - auto& values = this->handle->values; - auto index = values.find(key); - return index != values.end(); + auto& values = this->handle->values; + auto index = values.find(key); + return index != values.end(); } command_entry command_bulk::value(const std::string &key) { - auto& values = this->handle->values; - auto index = values.find(key); - if(index == values.end()) { - if(!this->handle->handle->editable) - throw command_value_missing_exception(this->bulk_index, key); + auto& values = this->handle->values; + auto index = values.find(key); + if(index == values.end()) { + if(!this->handle->handle->editable) + throw command_value_missing_exception(this->bulk_index, key); - auto result = make_shared(); - values[key] = result; - return command_entry(result); - } - return command_entry(index->second); + auto result = make_shared(); + values[key] = result; + return command_entry(result); + } + return command_entry(index->second); } const command_entry command_bulk::value(const std::string &key) const { - auto& values = this->handle->values; - auto index = values.find(key); - if(index == values.end()) - throw command_value_missing_exception(this->bulk_index, key); + auto& values = this->handle->values; + auto index = values.find(key); + if(index == values.end()) + throw command_value_missing_exception(this->bulk_index, key); - return command_entry(index->second); + return command_entry(index->second); } command_entry command_entry::empty{}; \ No newline at end of file diff --git a/src/query/command2.h b/src/query/command2.h index f754103..5f7e3e6 100644 --- a/src/query/command2.h +++ b/src/query/command2.h @@ -21,621 +21,621 @@ #endif namespace ts { - /* data impl stuff */ - namespace impl { - struct command_data; + /* data impl stuff */ + namespace impl { + struct command_data; - struct command_value { - bool casted = false; /* true if value isn't a std::string */ - std::any value; - std::string(*to_string)(const std::any&); - }; + struct command_value { + bool casted = false; /* true if value isn't a std::string */ + std::any value; + std::string(*to_string)(const std::any&); + }; - struct command_bulk { - command_data* handle; - std::map> values; - }; + struct command_bulk { + command_data* handle; + std::map> values; + }; - struct command_data { - std::string command; - bool editable; - std::deque> bulks; - std::deque triggers; - }; - } + struct command_data { + std::string command; + bool editable; + std::deque> bulks; + std::deque triggers; + }; + } - /* Container stuff */ - class command_bulk; - class command_entry; - class command { - public: - struct format { - enum value { - QUERY, - BRACE_ESCAPED_QUERY, - JSON - }; - }; - static command parse(const std::string_view& /* command data */, bool /* expect type */ = true, bool /* drop non UTF-8 characters */ = false); - explicit command(const std::string& /* command */ = "", bool /* editable */ = true); + /* Container stuff */ + class command_bulk; + class command_entry; + class command { + public: + struct format { + enum value { + QUERY, + BRACE_ESCAPED_QUERY, + JSON + }; + }; + static command parse(const std::string_view& /* command data */, bool /* expect type */ = true, bool /* drop non UTF-8 characters */ = false); + explicit command(const std::string& /* command */ = "", bool /* editable */ = true); - std::string identifier() const; - void set_identifier(const std::string& /* command */); + std::string identifier() const; + void set_identifier(const std::string& /* command */); - command_bulk bulk(size_t /* bulk index */); - const command_bulk bulk(size_t /* bulk index */) const; - size_t bulk_count() const; - inline command_bulk operator[](size_t /* index */); - inline const command_bulk operator[](size_t /* index */) const; + command_bulk bulk(size_t /* bulk index */); + const command_bulk bulk(size_t /* bulk index */) const; + size_t bulk_count() const; + inline command_bulk operator[](size_t /* index */); + inline const command_bulk operator[](size_t /* index */) const; - command_entry value(const std::string& /* key */); - const command_entry value(const std::string& /* key */) const; - bool has_value(const std::string& /* key */) const; - command_entry operator[](const std::string& /* key */); - const command_entry operator[](const std::string& /* key */) const; + command_entry value(const std::string& /* key */); + const command_entry value(const std::string& /* key */) const; + bool has_value(const std::string& /* key */) const; + command_entry operator[](const std::string& /* key */); + const command_entry operator[](const std::string& /* key */) const; - bool has_trigger(const std::string& /* key */) const; - void set_trigger(const std::string& /* key */, bool /* value */ = true); + bool has_trigger(const std::string& /* key */) const; + void set_trigger(const std::string& /* key */, bool /* value */ = true); - std::string build(format::value /* format */ = format::QUERY); - /* TODO add a json object build method */ - private: - std::shared_ptr handle; - }; + std::string build(format::value /* format */ = format::QUERY); + /* TODO add a json object build method */ + private: + std::shared_ptr handle; + }; - class command_bulk { - friend class command; - public: - bool has(const std::string& /* key */) const; - command_entry value(const std::string& /* key */); - command_entry const value(const std::string& /* key */) const; + class command_bulk { + friend class command; + public: + bool has(const std::string& /* key */) const; + command_entry value(const std::string& /* key */); + command_entry const value(const std::string& /* key */) const; - inline command_entry operator[](const std::string& /* key */); - inline const command_entry operator[](const std::string& /* key */) const; - private: - command_bulk(size_t index, std::shared_ptr handle) : bulk_index(index), handle(std::move(handle)) {} + inline command_entry operator[](const std::string& /* key */); + inline const command_entry operator[](const std::string& /* key */) const; + private: + command_bulk(size_t index, std::shared_ptr handle) : bulk_index(index), handle(std::move(handle)) {} - size_t bulk_index; - std::shared_ptr handle; - }; + size_t bulk_index; + std::shared_ptr handle; + }; - class command_entry { - public: - static command_entry empty; + class command_entry { + public: + static command_entry empty; - command_entry() : handle(std::make_shared()) {} - command_entry(const command_entry& ref) : handle(ref.handle) {} - command_entry(command_entry&& ref) : handle(std::move(ref.handle)) {} + command_entry() : handle(std::make_shared()) {} + command_entry(const command_entry& ref) : handle(ref.handle) {} + command_entry(command_entry&& ref) : handle(std::move(ref.handle)) {} - command_entry&operator=(const command_entry& other) { - this->handle = other.handle; - return *this; - } + command_entry&operator=(const command_entry& other) { + this->handle = other.handle; + return *this; + } - inline bool is_empty() const { return !this->handle->value.has_value(); } + inline bool is_empty() const { return !this->handle->value.has_value(); } - command_entry& reset() { - this->handle->value.reset(); - return *this; - } + command_entry& reset() { + this->handle->value.reset(); + return *this; + } - const std::string string() const { - if(this->is_empty()) return ""; + const std::string string() const { + if(this->is_empty()) return ""; - if(!this->handle->casted || this->handle->value.type() == typeid(std::string)) //No cast needed - return std::any_cast(this->handle->value); + if(!this->handle->casted || this->handle->value.type() == typeid(std::string)) //No cast needed + return std::any_cast(this->handle->value); - if(!this->handle->to_string) throw command_cannot_uncast_exception(); - return this->handle->to_string(this->handle->value); - } + if(!this->handle->to_string) throw command_cannot_uncast_exception(); + return this->handle->to_string(this->handle->value); + } - inline const std::string value() const { return (std::string) this->string(); } + inline const std::string value() const { return (std::string) this->string(); } - inline operator std::string() const { - return this->string(); - } + inline operator std::string() const { + return this->string(); + } - template ::value, int> = 0> - T as() { - static_assert(converter::supported, "Target type isn't supported!"); - static_assert(!converter::supported || converter::from_string, "Target type dosn't support parsing"); + template ::value, int> = 0> + T as() { + static_assert(converter::supported, "Target type isn't supported!"); + static_assert(!converter::supported || converter::from_string, "Target type dosn't support parsing"); - if(this->is_empty()) return T(); + if(this->is_empty()) return T(); - if(this->handle->casted) { - if(this->handle->value.type() == typeid(T)) - return std::any_cast(this->handle->value); - else - throw command_casted_exception(); - } else { - const auto& ref = std::any_cast(this->handle->value); - this->handle->value = converter::from_string(ref); - this->handle->to_string = converter::to_string; - this->handle->casted = true; - } + if(this->handle->casted) { + if(this->handle->value.type() == typeid(T)) + return std::any_cast(this->handle->value); + else + throw command_casted_exception(); + } else { + const auto& ref = std::any_cast(this->handle->value); + this->handle->value = converter::from_string(ref); + this->handle->to_string = converter::to_string; + this->handle->casted = true; + } - return std::any_cast(this->handle->value); - } + return std::any_cast(this->handle->value); + } - template ::value, int> = 0> - T as() { - return this->string(); - } + template ::value, int> = 0> + T as() { + return this->string(); + } - template - inline operator T() { - return this->as(); - } + template + inline operator T() { + return this->as(); + } - command_entry& melt() { - if(this->handle->casted) { - this->handle->value = this->handle->to_string(this->handle->value); - this->handle->casted = false; - this->handle->to_string = nullptr; - } - return *this; - } + command_entry& melt() { + if(this->handle->casted) { + this->handle->value = this->handle->to_string(this->handle->value); + this->handle->casted = false; + this->handle->to_string = nullptr; + } + return *this; + } - template ::value && !std::is_same::value && !std::is_same::value, int>::type = 0> - void set(const T& value) { - static_assert(converter::supported, "Target type isn't supported!"); - static_assert(!converter::supported || converter::to_string, "Target type dosn't support encode"); + template ::value && !std::is_same::value && !std::is_same::value, int>::type = 0> + void set(const T& value) { + static_assert(converter::supported, "Target type isn't supported!"); + static_assert(!converter::supported || converter::to_string, "Target type dosn't support encode"); - this->handle->casted = true; - this->handle->value = std::move(value); - this->handle->to_string = converter::to_string; - } + this->handle->casted = true; + this->handle->value = std::move(value); + this->handle->to_string = converter::to_string; + } - template ::value, int>::type = 0> - void set(const T& value) { - this->handle->value = value; - this->handle->casted = false; - this->handle->to_string = nullptr; - } + template ::value, int>::type = 0> + void set(const T& value) { + this->handle->value = value; + this->handle->casted = false; + this->handle->to_string = nullptr; + } - template - void set(const char (&string)[N]) { - this->set(std::string(string, N - 1)); - } + template + void set(const char (&string)[N]) { + this->set(std::string(string, N - 1)); + } - template - command_entry&operator=(const T& value) { - this->set(value); - return *this; - } + template + command_entry&operator=(const T& value) { + this->set(value); + return *this; + } - explicit command_entry(std::shared_ptr handle) : handle(std::move(handle)) {} + explicit command_entry(std::shared_ptr handle) : handle(std::move(handle)) {} - private: - std::shared_ptr handle; - }; + private: + std::shared_ptr handle; + }; - namespace descriptor { - namespace tliterals { - template - using tstring = std::integer_sequence; + namespace descriptor { + namespace tliterals { + template + using tstring = std::integer_sequence; #ifndef WIN32 - template - constexpr tstring operator""_tstr() { return { }; } + template + constexpr tstring operator""_tstr() { return { }; } #endif - template - struct tliteral; - - template - struct tliteral> { - static constexpr char string[sizeof...(elements) + 1] = { elements..., '\0' }; - }; - } - - namespace impl { - namespace templates { - template - struct _or_ { - constexpr static bool value = false; - }; - - template - struct _or_ { - constexpr static bool value = T || _or_::value; - }; - - template - struct index; - - template - struct tuple_index; - - template - struct index : std::integral_constant - { }; - - template - struct index : std::integral_constant::value> - { }; - - template - struct tuple_index> : std::integral_constant::value> - { }; - - template - struct remove_cr { - typedef T type; - }; - - template - struct remove_cr { - typedef T type; - }; - } - - struct base; - - template - struct field; - - struct field_data; - struct field_base; - struct optional_extend; - struct bulk_extend; - - template - struct command_parser { - constexpr static bool supported = false; - }; - - inline void parse_field(const std::shared_ptr& description, field_base* field, command& cmd); - - struct option_data { - bool bulked; - bool optional; - }; - - template - struct options { - using object_data_t = option_data; - static constexpr auto is_bulked = bulked_t; - static constexpr auto is_optional = optional_t; - - protected: - inline static object_data_t options_object() { - return { - is_bulked, - is_optional - }; - } - }; - using default_options = options; - - struct base { - virtual ~base() = default; - }; - - struct base_data { - int type; /* 1 = field | 2 = switch | 3 = command handle */ - option_data options; - }; - - struct field_base : public base { - virtual std::vector& ref_values() = 0; - virtual const std::vector& ref_values() const = 0; - }; - - struct field_data : public base_data { - const char* key; - const std::type_info& field_type; - - void* from_string; - void* to_string; - }; - - template - struct field : public field_base, public options, public extends... { - friend struct command_parser>; - static_assert(converter::supported, "Target type isn't supported!"); - static_assert(!converter::supported || converter::from_string, "Target type dosn't support parsing"); - static_assert(impl::templates::_or_::value...>::value == false, "Extensions could not have data members"); - - protected: - using object_t = field_data; - using value_type = value_type_t; - static constexpr auto key = key_t::string; - static constexpr auto from_string = converter::from_string; - - public: - template ::value...>::value, int> = 0 */> - using as_optional = field, optional_extend, extends...>; - - template ::value...>::value, int> = 0 */> - using as_bulked = field, bulk_extend, extends...>; - - using optional = as_optional; - using bulked = as_bulked; - - inline static std::shared_ptr describe() { - return std::make_shared( - object_t { - 1, - options::options_object(), - key, - typeid(value_type_t), - (void*) converter::from_string, - (void*) converter::to_string - } - ); - } - - inline value_type_t value() const { - command_entry& value = this->get_command_entry(); - return value.as(); - } - - inline command_entry& get_command_entry() const { - if(this->values.empty()) - throw command_value_missing_exception{0, key}; - - const auto& front = this->values.front(); - return *(command_entry*) &front; - } - - template - inline T as() const { - command_entry& value = this->get_command_entry(); - return value.as(); - } - - template - inline operator T() const { - return this->as(); - } - - std::vector& ref_values() final { return this->values; } - const std::vector& ref_values() const final { return this->values; } - protected: - std::vector values; - }; - - struct optional_extend { - public: - inline bool has_value() const { - auto base = dynamic_cast((struct base*) this); - assert(base); - - const auto& values = base->ref_values(); - return !values.empty() && !values[0].is_empty(); - } - - template - inline T get_or(T&& value = T{}) const { - auto base = dynamic_cast((struct base*) this); - assert(base); - - auto& values = base->ref_values(); - if(values.empty() || values[0].is_empty()) - return value; - - return values.front().as(); - } - }; - - struct bulk_extend { - public: - inline bool has_index(size_t index) const { - return !this->at(index).is_empty(); - } - - inline size_t length() const { - auto base = dynamic_cast((struct base*) this); - assert(base); - - return base->ref_values().size(); - } - - inline command_entry at(size_t index) const { - auto base = dynamic_cast((struct base*) this); - assert(base); - - auto& values = base->ref_values(); - if(index > values.size()) - throw command_bulk_exceed_index_exception(); - - return values[index]; - } - - inline command_entry operator[](size_t index) const { - return this->at(index); - } - }; - - struct trigger_base : public base { - virtual bool& ref_flag() = 0; - }; - - struct trigger_data : public base_data { - const char* key; - }; - - template - struct trigger : public trigger_base, public options { - protected: - static constexpr auto key = key_t::string; - public: - using object_t = trigger_data; - - inline static std::shared_ptr describe() { - return std::make_shared( - object_t { - 2, - options::options_object(), - key - } - ); - } - - inline bool is_set() const { return this->flag_set; } - operator bool() const { return this->flag_set; } - - bool& ref_flag() override { - return this->flag_set; - } - - private: - bool flag_set = false; - }; - - template - struct command_parser> { - constexpr static bool supported = true; - - typedef field field_t; - using descriptor_t = std::shared_ptr; - - inline static descriptor_t describe() { - return field_t::describe(); - } - - inline static field_t apply(descriptor_t& descriptor, command& cmd) { - assert(descriptor->type == 1); - - field_t result{}; - - //if(!description->options.optional && !cmd.has_value(description->key)) - // throw command_value_missing_exception(); - auto& values = result.ref_values(); - values.clear(); - - if(descriptor->options.bulked) { - values.resize(cmd.bulk_count()); - for(size_t bulk_index = 0; bulk_index < cmd.bulk_count(); bulk_index++) { - if(!cmd[bulk_index].has(descriptor->key)) { - if(!descriptor->options.optional) - throw command_value_missing_exception(bulk_index, descriptor->key); - else - values[bulk_index] = command_entry::empty; - } else { - values[bulk_index] = cmd[bulk_index][descriptor->key]; - } - } - } else { - if(!cmd.has_value(descriptor->key)) { - if(!descriptor->options.optional) - throw command_value_missing_exception(0, descriptor->key); - else - values.push_back(command_entry::empty); - } else - values.push_back(cmd[descriptor->key]); - } - - return result; - } - }; - - template - struct command_parser> { - constexpr static bool supported = true; - - typedef trigger trigger_t; - using descriptor_t = std::shared_ptr; - - inline static descriptor_t describe() { - return trigger_t::describe(); - } - - inline static trigger_t apply(descriptor_t& descriptor, command& cmd) { - assert(descriptor->type == 2); - - trigger_t result{}; - result.ref_flag() = cmd.has_trigger(descriptor->key); - return result; - } - }; - - struct command_data : public base_data { }; - - template <> - struct command_parser { - constexpr static bool supported = true; - - using descriptor_t = std::shared_ptr; - - inline static descriptor_t describe() { return std::make_shared(command_data{{3, {false, false}}}); } - - inline static command& apply(descriptor_t& descriptor, command& cmd) { - assert(descriptor->type == 3); - return cmd; - } - }; - - template - struct command_parser { - constexpr static bool supported = false; - - using descriptor_t = std::shared_ptr; - - inline static descriptor_t describe() { - return nullptr; - } - - inline static command& apply(descriptor_t& descriptor, command& cmd) { - return cmd; - } - }; - } - - template - using field = impl::field; - - template - using trigger = impl::trigger; - - template - inline std::array, sizeof...(args_t)> describe_function(void(*)(args_t...)) { - static_assert(!impl::templates::_or_::type>::supported...>::value, "Not any function argument type is supported"); - return {impl::command_parser::type>::describe()...}; - } - - struct invocable_function { - void operator()(command& command) { this->invoke(command); } - - virtual void invoke(command& command) = 0; - }; - - template - struct typed_invocable_function : public invocable_function { - using args_tuple_t = std::tuple; - template - using command_parser_t = impl::command_parser::type>; - using descriptors_t = std::tuple::descriptor_t...>; - - descriptors_t descriptors; - void(*function)(args_t...); - - void invoke(command& command) override { - this->function(command_parser_t::apply(std::get::value>(descriptors), command)...); - } - }; - - template > - std::shared_ptr parse_function(void(*function)(args_t...)) { - auto result = std::make_shared(); - result->function = function; - result->descriptors = {impl::command_parser::type>::describe()...}; - return result; - } - - template - void invoke_function(void(*function)(args_t...), command& command) { - auto descriptor = parse_function(function); - (*descriptor)(command); - } + template + struct tliteral; + + template + struct tliteral> { + static constexpr char string[sizeof...(elements) + 1] = { elements..., '\0' }; + }; + } + + namespace impl { + namespace templates { + template + struct _or_ { + constexpr static bool value = false; + }; + + template + struct _or_ { + constexpr static bool value = T || _or_::value; + }; + + template + struct index; + + template + struct tuple_index; + + template + struct index : std::integral_constant + { }; + + template + struct index : std::integral_constant::value> + { }; + + template + struct tuple_index> : std::integral_constant::value> + { }; + + template + struct remove_cr { + typedef T type; + }; + + template + struct remove_cr { + typedef T type; + }; + } + + struct base; + + template + struct field; + + struct field_data; + struct field_base; + struct optional_extend; + struct bulk_extend; + + template + struct command_parser { + constexpr static bool supported = false; + }; + + inline void parse_field(const std::shared_ptr& description, field_base* field, command& cmd); + + struct option_data { + bool bulked; + bool optional; + }; + + template + struct options { + using object_data_t = option_data; + static constexpr auto is_bulked = bulked_t; + static constexpr auto is_optional = optional_t; + + protected: + inline static object_data_t options_object() { + return { + is_bulked, + is_optional + }; + } + }; + using default_options = options; + + struct base { + virtual ~base() = default; + }; + + struct base_data { + int type; /* 1 = field | 2 = switch | 3 = command handle */ + option_data options; + }; + + struct field_base : public base { + virtual std::vector& ref_values() = 0; + virtual const std::vector& ref_values() const = 0; + }; + + struct field_data : public base_data { + const char* key; + const std::type_info& field_type; + + void* from_string; + void* to_string; + }; + + template + struct field : public field_base, public options, public extends... { + friend struct command_parser>; + static_assert(converter::supported, "Target type isn't supported!"); + static_assert(!converter::supported || converter::from_string, "Target type dosn't support parsing"); + static_assert(impl::templates::_or_::value...>::value == false, "Extensions could not have data members"); + + protected: + using object_t = field_data; + using value_type = value_type_t; + static constexpr auto key = key_t::string; + static constexpr auto from_string = converter::from_string; + + public: + template ::value...>::value, int> = 0 */> + using as_optional = field, optional_extend, extends...>; + + template ::value...>::value, int> = 0 */> + using as_bulked = field, bulk_extend, extends...>; + + using optional = as_optional; + using bulked = as_bulked; + + inline static std::shared_ptr describe() { + return std::make_shared( + object_t { + 1, + options::options_object(), + key, + typeid(value_type_t), + (void*) converter::from_string, + (void*) converter::to_string + } + ); + } + + inline value_type_t value() const { + command_entry& value = this->get_command_entry(); + return value.as(); + } + + inline command_entry& get_command_entry() const { + if(this->values.empty()) + throw command_value_missing_exception{0, key}; + + const auto& front = this->values.front(); + return *(command_entry*) &front; + } + + template + inline T as() const { + command_entry& value = this->get_command_entry(); + return value.as(); + } + + template + inline operator T() const { + return this->as(); + } + + std::vector& ref_values() final { return this->values; } + const std::vector& ref_values() const final { return this->values; } + protected: + std::vector values; + }; + + struct optional_extend { + public: + inline bool has_value() const { + auto base = dynamic_cast((struct base*) this); + assert(base); + + const auto& values = base->ref_values(); + return !values.empty() && !values[0].is_empty(); + } + + template + inline T get_or(T&& value = T{}) const { + auto base = dynamic_cast((struct base*) this); + assert(base); + + auto& values = base->ref_values(); + if(values.empty() || values[0].is_empty()) + return value; + + return values.front().as(); + } + }; + + struct bulk_extend { + public: + inline bool has_index(size_t index) const { + return !this->at(index).is_empty(); + } + + inline size_t length() const { + auto base = dynamic_cast((struct base*) this); + assert(base); + + return base->ref_values().size(); + } + + inline command_entry at(size_t index) const { + auto base = dynamic_cast((struct base*) this); + assert(base); + + auto& values = base->ref_values(); + if(index > values.size()) + throw command_bulk_exceed_index_exception(); + + return values[index]; + } + + inline command_entry operator[](size_t index) const { + return this->at(index); + } + }; + + struct trigger_base : public base { + virtual bool& ref_flag() = 0; + }; + + struct trigger_data : public base_data { + const char* key; + }; + + template + struct trigger : public trigger_base, public options { + protected: + static constexpr auto key = key_t::string; + public: + using object_t = trigger_data; + + inline static std::shared_ptr describe() { + return std::make_shared( + object_t { + 2, + options::options_object(), + key + } + ); + } + + inline bool is_set() const { return this->flag_set; } + operator bool() const { return this->flag_set; } + + bool& ref_flag() override { + return this->flag_set; + } + + private: + bool flag_set = false; + }; + + template + struct command_parser> { + constexpr static bool supported = true; + + typedef field field_t; + using descriptor_t = std::shared_ptr; + + inline static descriptor_t describe() { + return field_t::describe(); + } + + inline static field_t apply(descriptor_t& descriptor, command& cmd) { + assert(descriptor->type == 1); + + field_t result{}; + + //if(!description->options.optional && !cmd.has_value(description->key)) + // throw command_value_missing_exception(); + auto& values = result.ref_values(); + values.clear(); + + if(descriptor->options.bulked) { + values.resize(cmd.bulk_count()); + for(size_t bulk_index = 0; bulk_index < cmd.bulk_count(); bulk_index++) { + if(!cmd[bulk_index].has(descriptor->key)) { + if(!descriptor->options.optional) + throw command_value_missing_exception(bulk_index, descriptor->key); + else + values[bulk_index] = command_entry::empty; + } else { + values[bulk_index] = cmd[bulk_index][descriptor->key]; + } + } + } else { + if(!cmd.has_value(descriptor->key)) { + if(!descriptor->options.optional) + throw command_value_missing_exception(0, descriptor->key); + else + values.push_back(command_entry::empty); + } else + values.push_back(cmd[descriptor->key]); + } + + return result; + } + }; + + template + struct command_parser> { + constexpr static bool supported = true; + + typedef trigger trigger_t; + using descriptor_t = std::shared_ptr; + + inline static descriptor_t describe() { + return trigger_t::describe(); + } + + inline static trigger_t apply(descriptor_t& descriptor, command& cmd) { + assert(descriptor->type == 2); + + trigger_t result{}; + result.ref_flag() = cmd.has_trigger(descriptor->key); + return result; + } + }; + + struct command_data : public base_data { }; + + template <> + struct command_parser { + constexpr static bool supported = true; + + using descriptor_t = std::shared_ptr; + + inline static descriptor_t describe() { return std::make_shared(command_data{{3, {false, false}}}); } + + inline static command& apply(descriptor_t& descriptor, command& cmd) { + assert(descriptor->type == 3); + return cmd; + } + }; + + template + struct command_parser { + constexpr static bool supported = false; + + using descriptor_t = std::shared_ptr; + + inline static descriptor_t describe() { + return nullptr; + } + + inline static command& apply(descriptor_t& descriptor, command& cmd) { + return cmd; + } + }; + } + + template + using field = impl::field; + + template + using trigger = impl::trigger; + + template + inline std::array, sizeof...(args_t)> describe_function(void(*)(args_t...)) { + static_assert(!impl::templates::_or_::type>::supported...>::value, "Not any function argument type is supported"); + return {impl::command_parser::type>::describe()...}; + } + + struct invocable_function { + void operator()(command& command) { this->invoke(command); } + + virtual void invoke(command& command) = 0; + }; + + template + struct typed_invocable_function : public invocable_function { + using args_tuple_t = std::tuple; + template + using command_parser_t = impl::command_parser::type>; + using descriptors_t = std::tuple::descriptor_t...>; + + descriptors_t descriptors; + void(*function)(args_t...); + + void invoke(command& command) override { + this->function(command_parser_t::apply(std::get::value>(descriptors), command)...); + } + }; + + template > + std::shared_ptr parse_function(void(*function)(args_t...)) { + auto result = std::make_shared(); + result->function = function; + result->descriptors = {impl::command_parser::type>::describe()...}; + return result; + } + + template + void invoke_function(void(*function)(args_t...), command& command) { + auto descriptor = parse_function(function); + (*descriptor)(command); + } - /* converts a literal into a template literal */ - #define _tlit(literal) ::ts::descriptor::tliterals::tliteral - #define tl(lit) _tlit(lit) - } + /* converts a literal into a template literal */ + #define _tlit(literal) ::ts::descriptor::tliterals::tliteral + #define tl(lit) _tlit(lit) + } - //using desc = descriptor::base; + //using desc = descriptor::base; } #include "command_internal.h" \ No newline at end of file diff --git a/src/query/command_constants.h b/src/query/command_constants.h index ac7baf0..af5e307 100644 --- a/src/query/command_constants.h +++ b/src/query/command_constants.h @@ -4,25 +4,25 @@ #include "command2.h" namespace ts { - namespace cconstants { + namespace cconstants { - typedef descriptor::field return_code; + typedef descriptor::field return_code; - typedef descriptor::field server_id; + typedef descriptor::field server_id; - typedef descriptor::field client_id; - typedef descriptor::field client_database_id; + typedef descriptor::field client_id; + typedef descriptor::field client_database_id; - typedef descriptor::field channel_id; - typedef descriptor::field channel_parent_id; + typedef descriptor::field channel_id; + typedef descriptor::field channel_parent_id; - typedef descriptor::field channel_group_id; - typedef descriptor::field server_group_id; + typedef descriptor::field channel_group_id; + typedef descriptor::field server_group_id; - //FIXME - /* typedef descriptor::field permission_id; - typedef descriptor::field permission_name; - typedef descriptor::field permission_value; - */ - } + //FIXME + /* typedef descriptor::field permission_id; + typedef descriptor::field permission_name; + typedef descriptor::field permission_value; + */ + } } \ No newline at end of file diff --git a/src/query/command_exception.h b/src/query/command_exception.h index 898bf3f..6aa8434 100644 --- a/src/query/command_exception.h +++ b/src/query/command_exception.h @@ -1,26 +1,26 @@ #pragma once namespace ts { - class command_exception : public std::exception {}; + class command_exception : public std::exception {}; - class command_casted_exception : public command_exception { }; - class command_cannot_uncast_exception : public command_exception { }; - class command_bulk_exceed_index_exception : public command_exception { }; - class command_value_missing_exception : public command_exception { - public: - command_value_missing_exception(size_t index, std::string key) : _index(index), _key(move(key)) { } + class command_casted_exception : public command_exception { }; + class command_cannot_uncast_exception : public command_exception { }; + class command_bulk_exceed_index_exception : public command_exception { }; + class command_value_missing_exception : public command_exception { + public: + command_value_missing_exception(size_t index, std::string key) : _index(index), _key(move(key)) { } - inline size_t index() const { return this->_index; } - inline std::string key() const { return this->_key; } - private: - size_t _index; - std::string _key; - }; - class command_malformed_exception : public command_exception { - public: - command_malformed_exception(size_t index) : _index(index) {} - inline size_t index() const { return this->_index; } - private: - size_t _index; - }; + inline size_t index() const { return this->_index; } + inline std::string key() const { return this->_key; } + private: + size_t _index; + std::string _key; + }; + class command_malformed_exception : public command_exception { + public: + command_malformed_exception(size_t index) : _index(index) {} + inline size_t index() const { return this->_index; } + private: + size_t _index; + }; } \ No newline at end of file diff --git a/src/query/command_internal.h b/src/query/command_internal.h index 6c50daf..f2cc973 100644 --- a/src/query/command_internal.h +++ b/src/query/command_internal.h @@ -1,30 +1,30 @@ #pragma once namespace ts { - /* some inlineable implementations */ - inline command_bulk command::operator[](size_t index) { - return this->bulk(index); - } + /* some inlineable implementations */ + inline command_bulk command::operator[](size_t index) { + return this->bulk(index); + } - inline command_entry command::operator[](const std::string &key) { - return this->value(key); - } + inline command_entry command::operator[](const std::string &key) { + return this->value(key); + } - inline command_entry command_bulk::operator[](const std::string &key) { - return this->value(key); - } + inline command_entry command_bulk::operator[](const std::string &key) { + return this->value(key); + } - inline const command_bulk command::operator[](size_t index) const { - return this->bulk(index); - } + inline const command_bulk command::operator[](size_t index) const { + return this->bulk(index); + } - inline const command_entry command::operator[](const std::string &key) const { - return this->value(key); - } + inline const command_entry command::operator[](const std::string &key) const { + return this->value(key); + } - inline const command_entry command_bulk::operator[](const std::string &key) const { - return this->value(key); - } + inline const command_entry command_bulk::operator[](const std::string &key) const { + return this->value(key); + } } #ifndef WIN32 diff --git a/src/query/escape.cpp b/src/query/escape.cpp index ccd7013..0044d34 100644 --- a/src/query/escape.cpp +++ b/src/query/escape.cpp @@ -5,38 +5,38 @@ using namespace ts; using namespace std; std::string query::escape(std::string in) { - size_t index = 0; - while(index < in.length()) { - if(in[index] == '\\') - in.replace(index, 1, "\\\\", 2); - else if(in[index] == ' ') - in.replace(index, 1, "\\s", 2); - else if(in[index] == '/') - in.replace(index, 1, "\\/", 2); - else if(in[index] == '|') - in.replace(index, 1, "\\p", 2); - else if(in[index] == '\b') - in.replace(index, 1, "\\b", 2); - else if(in[index] == '\f') - in.replace(index, 1, "\\f", 2); - else if(in[index] == '\n') - in.replace(index, 1, "\\n", 2); - else if(in[index] == '\r') - in.replace(index, 1, "\\r", 2); - else if(in[index] == '\t') - in.replace(index, 1, "\\t", 2); - else if(in[index] == '\x07') - in.replace(index, 1, "\\a", 2); - else if(in[index] == '\x0B') - in.replace(index, 1, "\\v", 2); - else { - index += 1; - continue; - } - index += 2; - } + size_t index = 0; + while(index < in.length()) { + if(in[index] == '\\') + in.replace(index, 1, "\\\\", 2); + else if(in[index] == ' ') + in.replace(index, 1, "\\s", 2); + else if(in[index] == '/') + in.replace(index, 1, "\\/", 2); + else if(in[index] == '|') + in.replace(index, 1, "\\p", 2); + else if(in[index] == '\b') + in.replace(index, 1, "\\b", 2); + else if(in[index] == '\f') + in.replace(index, 1, "\\f", 2); + else if(in[index] == '\n') + in.replace(index, 1, "\\n", 2); + else if(in[index] == '\r') + in.replace(index, 1, "\\r", 2); + else if(in[index] == '\t') + in.replace(index, 1, "\\t", 2); + else if(in[index] == '\x07') + in.replace(index, 1, "\\a", 2); + else if(in[index] == '\x0B') + in.replace(index, 1, "\\v", 2); + else { + index += 1; + continue; + } + index += 2; + } - return in; + return in; } /* @@ -46,98 +46,98 @@ if (input[i] = $ED) and // Prüfe auf High and Low Surrogate (input[i+4] or $F = $BF) then begin output := output + - AnsiChar((input[i+1] and $F + 1) shr 2 and 7 or $F0) + // and 7 kann man auch weglassen - AnsiChar((input[i+2] shr 2 and $F + (input[i+1] and $F + 1) shl 4 and $30) or $80) + - AnsiChar((input[i+4] and $F + input[i+2] shl 4 and $30) or $80) + - AnsiChar(input[i+5]); + AnsiChar((input[i+1] and $F + 1) shr 2 and 7 or $F0) + // and 7 kann man auch weglassen + AnsiChar((input[i+2] shr 2 and $F + (input[i+1] and $F + 1) shl 4 and $30) or $80) + + AnsiChar((input[i+4] and $F + input[i+2] shl 4 and $30) or $80) + + AnsiChar(input[i+5]); end else output := output + AnsiChar(input); */ std::string query::unescape(std::string in, bool throw_error) { - size_t index = 0; - while(index < in.length()){ - if(in[index] == '\\'){ - if(in.length() <= index + 1) break; - char replace = 0; + size_t index = 0; + while(index < in.length()){ + if(in[index] == '\\'){ + if(in.length() <= index + 1) break; + char replace = 0; - switch (in[index + 1]){ - case 's': replace = ' '; break; - case '/': replace = '/'; break; - case 'p': replace = '|'; break; - case 'b': replace = '\b'; break; - case 'f': replace = '\f'; break; - case 'n': replace = '\n'; break; - case 'r': replace = '\r'; break; - case 't': replace = '\t'; break; - case 'a': replace = '\x07'; break; - case 'v': replace = '\x0B'; break; - case '\\': replace = '\\'; break; - default: - replace = '\x00'; break; - } - if(replace != 0x00) - in.replace(index, 2, string(&replace, 1)); - } + switch (in[index + 1]){ + case 's': replace = ' '; break; + case '/': replace = '/'; break; + case 'p': replace = '|'; break; + case 'b': replace = '\b'; break; + case 'f': replace = '\f'; break; + case 'n': replace = '\n'; break; + case 'r': replace = '\r'; break; + case 't': replace = '\t'; break; + case 'a': replace = '\x07'; break; + case 'v': replace = '\x0B'; break; + case '\\': replace = '\\'; break; + default: + replace = '\x00'; break; + } + if(replace != 0x00) + in.replace(index, 2, string(&replace, 1)); + } - uint8_t current = (uint8_t) in[index]; - if(in.length() - index >= 6) { //Check for CESU-8 - if((current == 0xED) && ((uint8_t) in[index + 3] == 0xED) && ((((uint8_t) in[index + 1] | 0xF) == 0xAF)) && ((((uint8_t) in[index + 4] | 0xF) == 0xBF))){ - char replaced[4]; + uint8_t current = (uint8_t) in[index]; + if(in.length() - index >= 6) { //Check for CESU-8 + if((current == 0xED) && ((uint8_t) in[index + 3] == 0xED) && ((((uint8_t) in[index + 1] | 0xF) == 0xAF)) && ((((uint8_t) in[index + 4] | 0xF) == 0xBF))){ + char replaced[4]; - replaced[0] = (((((uint8_t) in[index + 1] & 0xF) + 1) >> 2) & 7) | 0xF0; - replaced[1] = ((((uint8_t) in[index + 2] >> 2) & 0xF) + (((((uint8_t) in[index + 1] & 0xF)) + (1 << 4)) | 0x80)); - replaced[2] = (((uint8_t) in[index + 4] & 0xF) + (((uint8_t) in[index + 2] << 4) & 0x30)) | 0x80; - replaced[3] = ((uint8_t) in[index + 5]); + replaced[0] = (((((uint8_t) in[index + 1] & 0xF) + 1) >> 2) & 7) | 0xF0; + replaced[1] = ((((uint8_t) in[index + 2] >> 2) & 0xF) + (((((uint8_t) in[index + 1] & 0xF)) + (1 << 4)) | 0x80)); + replaced[2] = (((uint8_t) in[index + 4] & 0xF) + (((uint8_t) in[index + 2] << 4) & 0x30)) | 0x80; + replaced[3] = ((uint8_t) in[index + 5]); - in.replace(index, 6, string(replaced, 4)); - index -= 2; //Substract the replace difference + in.replace(index, 6, string(replaced, 4)); + index -= 2; //Substract the replace difference - index += 5; //Skip 5 bytes (CESU-8 length for emoty) - } - } - //"\221\210\200\200\200\210\221\221\221\221\204\210\221\221\221\221\221\221\221\221\221\204\210\221\221\221\221\221\204\210\221\221" - if(current >= 128) { //UTF8 check - if(current >= 192 && (current <= 193 || current >= 245)) { - in.replace(index, 1, "", 0); //Cut the character out - index--; - } else if(current >= 194 && current <= 223) { - if(in.length() - index <= 1) - in.replace(index, in.length() - index, "", 0); - else if((uint8_t) in[index + 1] >= 128 && (uint8_t) in[index + 1] <= 191) index += 1; //Valid - else { - if(throw_error) throw invalid_argument("Invalid UTF-8 character at index " + to_string(index)); - in.replace(index, 2, "", 0); //Cut the two characters out - index--; - } - } else if(current >= 224 && current <= 239) { - if(in.length() - index <= 2) - in.replace(index, in.length() - index, "", 0); - else if((uint8_t) in[index + 1] >= 128 && (uint8_t) in[index + 1] <= 191 && - (uint8_t) in[index + 2] >= 128 && (uint8_t) in[index + 2] <= 191) index += 2; //Valid - else { - if(throw_error) throw invalid_argument("Invalid UTF-8 character at index " + to_string(index)); - in.replace(index, 3, "", 0); //Cut the three characters out - index--; - } - } else if(current >= 240 && current <= 244) { - if(in.length() - index <= 3) - in.replace(index, in.length() - index, "", 0); - else if((uint8_t) in[index + 1] >= 128 && (uint8_t) in[index + 1] <= 191 && - (uint8_t) in[index + 2] >= 128 && (uint8_t) in[index + 2] <= 191 && - (uint8_t) in[index + 3] >= 128 && (uint8_t) in[index + 3] <= 191) index += 3; //Valid - else { - if(throw_error) throw invalid_argument("Invalid UTF-8 character at index " + to_string(index)); - in.replace(index, 4, "", 0); //Cut the three characters out - index--; - } - } else { - if(throw_error) throw invalid_argument("Invalid UTF-8 character at index " + to_string(index)); - in.replace(index, 1, "", 0); //Cut the character out - index--; - } - } - index++; - } - return in; + index += 5; //Skip 5 bytes (CESU-8 length for emoty) + } + } + //"\221\210\200\200\200\210\221\221\221\221\204\210\221\221\221\221\221\221\221\221\221\204\210\221\221\221\221\221\204\210\221\221" + if(current >= 128) { //UTF8 check + if(current >= 192 && (current <= 193 || current >= 245)) { + in.replace(index, 1, "", 0); //Cut the character out + index--; + } else if(current >= 194 && current <= 223) { + if(in.length() - index <= 1) + in.replace(index, in.length() - index, "", 0); + else if((uint8_t) in[index + 1] >= 128 && (uint8_t) in[index + 1] <= 191) index += 1; //Valid + else { + if(throw_error) throw invalid_argument("Invalid UTF-8 character at index " + to_string(index)); + in.replace(index, 2, "", 0); //Cut the two characters out + index--; + } + } else if(current >= 224 && current <= 239) { + if(in.length() - index <= 2) + in.replace(index, in.length() - index, "", 0); + else if((uint8_t) in[index + 1] >= 128 && (uint8_t) in[index + 1] <= 191 && + (uint8_t) in[index + 2] >= 128 && (uint8_t) in[index + 2] <= 191) index += 2; //Valid + else { + if(throw_error) throw invalid_argument("Invalid UTF-8 character at index " + to_string(index)); + in.replace(index, 3, "", 0); //Cut the three characters out + index--; + } + } else if(current >= 240 && current <= 244) { + if(in.length() - index <= 3) + in.replace(index, in.length() - index, "", 0); + else if((uint8_t) in[index + 1] >= 128 && (uint8_t) in[index + 1] <= 191 && + (uint8_t) in[index + 2] >= 128 && (uint8_t) in[index + 2] <= 191 && + (uint8_t) in[index + 3] >= 128 && (uint8_t) in[index + 3] <= 191) index += 3; //Valid + else { + if(throw_error) throw invalid_argument("Invalid UTF-8 character at index " + to_string(index)); + in.replace(index, 4, "", 0); //Cut the three characters out + index--; + } + } else { + if(throw_error) throw invalid_argument("Invalid UTF-8 character at index " + to_string(index)); + in.replace(index, 1, "", 0); //Cut the character out + index--; + } + } + index++; + } + return in; } \ No newline at end of file diff --git a/src/query/escape.h b/src/query/escape.h index fb00bed..343b2a0 100644 --- a/src/query/escape.h +++ b/src/query/escape.h @@ -3,8 +3,8 @@ #include namespace ts { - namespace query { - extern std::string escape(std::string); - extern std::string unescape(std::string, bool /* throw error */); - } + namespace query { + extern std::string escape(std::string); + extern std::string unescape(std::string, bool /* throw error */); + } } \ No newline at end of file diff --git a/src/sql/SqlQuery.cpp b/src/sql/SqlQuery.cpp index 75dbc39..8aa4837 100644 --- a/src/sql/SqlQuery.cpp +++ b/src/sql/SqlQuery.cpp @@ -10,8 +10,8 @@ using namespace std::chrono; namespace sql { result result::success = result("", 0, "success"); sql::command model::command() { return ::sql::command(*this); } - sql::model model::copy() { return sql::model(this->_data); } - model::model(const std::shared_ptr& data) : command_base(data->handle->copyCommandData(data)) {} + sql::model model::copy() { return sql::model(this->_data); } + model::model(const std::shared_ptr& data) : command_base(data->handle->copyCommandData(data)) {} /** * Command class itself */ @@ -30,7 +30,7 @@ namespace sql { threads::Future AsyncSqlPool::executeLater(const command& cmd) { threads::Future fut; this->_threads->execute([cmd, fut]{ //cmd for copy and stmt survive - command copy = cmd; + command copy = cmd; result res; while((res = copy.execute()).code() == SQLITE_BUSY){ cerr << "Execute busy!" << endl; diff --git a/src/sql/SqlQuery.h b/src/sql/SqlQuery.h index bf8d529..eceac7c 100644 --- a/src/sql/SqlQuery.h +++ b/src/sql/SqlQuery.h @@ -19,10 +19,10 @@ namespace sql { class SqlManager; class AsyncSqlPool; class command; - class model; - namespace impl { - template class command_base; - } + class model; + namespace impl { + template class command_base; + } inline std::ostream& operator<<(std::ostream& s,const result& res); inline std::ostream& operator<<(std::ostream& s,const result* res); @@ -34,10 +34,10 @@ namespace sql { static result success; result() : result(success) { } result(std::string query, int code, std::string msg) : _code(code), _msg(std::move(msg)), _sql(std::move(query)) { } - result(int code, const std::string &msg) : _code(code), _msg(std::move(msg)) { } - result(const result& ref) : _code(ref._code), _msg(ref._msg), _sql(ref._sql) { } + result(int code, const std::string &msg) : _code(code), _msg(std::move(msg)) { } + result(const result& ref) : _code(ref._code), _msg(ref._msg), _sql(ref._sql) { } result(result&& ref) : _code(ref._code), _msg(std::move(ref._msg)), _sql(std::move(ref._sql)) { } - virtual ~result() { }; + virtual ~result() { }; int code() const { return _code; } std::string msg() const { return _msg; } @@ -49,7 +49,7 @@ namespace sql { result&operator=(const result& other) { this->_code = other._code; this->_msg = other._msg; - this->_sql = other._sql; + this->_sql = other._sql; return *this; } @@ -87,7 +87,7 @@ namespace sql { class SqlManager { template friend class impl::command_base; friend class command; - friend class model; + friend class model; public: explicit SqlManager(SqlType); virtual ~SqlManager(); @@ -109,17 +109,17 @@ namespace sql { }; #define SQL_FWD(...) ::std::forward(__VA_ARGS__) - namespace impl { - template - struct merge; + namespace impl { + template + struct merge; - template - struct merge, std::tuple> { - using result = std::tuple; - }; + template + struct merge, std::tuple> { + using result = std::tuple; + }; - /* let me stuff reverse */ - template + /* let me stuff reverse */ + template struct append_reversed { }; template @@ -137,10 +137,10 @@ namespace sql { using type = typename append_reversed::type>::type; }; - /* Return type stuff */ + /* Return type stuff */ typedef int stardart_return_type; - template - using stardart_return = std::function; + template + using stardart_return = std::function; template struct transformer_return { @@ -257,64 +257,64 @@ namespace sql { } }; - template - class command_base { - friend class ::sql::command; - friend class ::sql::model; - public: - command_base(SqlManager* handle, const std::string &sql, std::initializer_list values) { - assert(handle); - assert(!sql.empty()); - this->_data = handle->allocateCommandData(); - this->_data->handle = handle; - this->_data->sql_command = sql; - this->__data = this->_data.get(); - for(const auto& val : values) this->value(val); + template + class command_base { + friend class ::sql::command; + friend class ::sql::model; + public: + command_base(SqlManager* handle, const std::string &sql, std::initializer_list values) { + assert(handle); + assert(!sql.empty()); + this->_data = handle->allocateCommandData(); + this->_data->handle = handle; + this->_data->sql_command = sql; + this->__data = this->_data.get(); + for(const auto& val : values) this->value(val); } - template - command_base(SqlManager* handle, std::string sql, Ts&&... vars) : command_base(handle, sql, {}) { values(vars...); } + template + command_base(SqlManager* handle, std::string sql, Ts&&... vars) : command_base(handle, sql, {}) { values(vars...); } - command_base(const command_base& ref) : _data(ref._data), __data(ref._data.get()) {} - command_base(command_base&& ref) noexcept : _data(ref._data), __data(ref._data.get()) { } + command_base(const command_base& ref) : _data(ref._data), __data(ref._data.get()) {} + command_base(command_base&& ref) noexcept : _data(ref._data), __data(ref._data.get()) { } - virtual ~command_base() = default; + virtual ~command_base() = default; - virtual SelfType& value(const variable& val) { - this->_data->variables.push_back(val); - return *(SelfType*) this; - } + virtual SelfType& value(const variable& val) { + this->_data->variables.push_back(val); + return *(SelfType*) this; + } - template - SelfType& value(const std::initializer_list& val) { - //this->_data->variables.push_back(val.begin()); - return *(SelfType*) this; - } + template + SelfType& value(const std::initializer_list& val) { + //this->_data->variables.push_back(val.begin()); + return *(SelfType*) this; + } - template - SelfType& value(const std::string& key, T&& value) { - this->_data->variables.push_back(variable{key, value}); + template + SelfType& value(const std::string& key, T&& value) { + this->_data->variables.push_back(variable{key, value}); - return *(SelfType*) this; - } + return *(SelfType*) this; + } - SelfType& values(){ return *(SelfType*) this; } + SelfType& values(){ return *(SelfType*) this; } - template - SelfType& values(const value_t& firstValue, values_t&&... values){ - this->value(firstValue); - this->values(values...); - return *(SelfType*) this; - } + template + SelfType& values(const value_t& firstValue, values_t&&... values){ + this->value(firstValue); + this->values(values...); + return *(SelfType*) this; + } - std::string sqlCommand(){ return _data->sql_command; } - SqlManager* handle(){ return _data->handle; } - protected: - explicit command_base(const std::shared_ptr& data) : _data(data), __data(data.get()) {} - std::shared_ptr _data; - CommandData* __data = nullptr; - }; - } + std::string sqlCommand(){ return _data->sql_command; } + SqlManager* handle(){ return _data->handle; } + protected: + explicit command_base(const std::shared_ptr& data) : _data(data), __data(data.get()) {} + std::shared_ptr _data; + CommandData* __data = nullptr; + }; + } class model : public impl::command_base { public: @@ -324,38 +324,38 @@ namespace sql { model(SqlManager* handle, const std::string &sql, Ts... vars) : model(handle, sql, {}) { values(vars...); } model(const model& v) : command_base(v) {}; - model(model&& v) noexcept : command_base(v){}; + model(model&& v) noexcept : command_base(v){}; ~model() override {}; sql::command command(); - sql::model copy(); + sql::model copy(); - private: - explicit model(const std::shared_ptr&); + private: + explicit model(const std::shared_ptr&); }; class command : public impl::command_base { public: - command(SqlManager* db, const std::string &sql, std::initializer_list values) : command_base(db, sql, values) {}; + command(SqlManager* db, const std::string &sql, std::initializer_list values) : command_base(db, sql, values) {}; - template - command(SqlManager* handle, const std::string &sql, Ts... vars) : command_base(handle, sql, {}) { values(SQL_FWD(vars)...); } - + template + command(SqlManager* handle, const std::string &sql, Ts... vars) : command_base(handle, sql, {}) { values(SQL_FWD(vars)...); } + /* - template + template command(SqlManager* handle, const std::string &sql, std::initializer_list arg_0, std::initializer_list arg_1) : command_base(handle, sql, {}) { - //static_assert(false, "testing"); + //static_assert(false, "testing"); } - command(SqlManager* handle, const std::string &sql) : command_base(handle, sql, {}) {} - */ + command(SqlManager* handle, const std::string &sql) : command_base(handle, sql, {}) {} + */ explicit command(model& c) : command_base(c.handle(), c.sqlCommand()) { this->_data = c._data->handle->copyCommandData(c._data); } command(const command& v): command_base(v) {}; - command(command&& v) noexcept : command_base(v){}; + command(command&& v) noexcept : command_base(v){}; ~command() override = default;; result execute() { diff --git a/src/sql/mysql/MySQL.cpp b/src/sql/mysql/MySQL.cpp index 4088665..fbb44bc 100644 --- a/src/sql/mysql/MySQL.cpp +++ b/src/sql/mysql/MySQL.cpp @@ -27,831 +27,831 @@ MySQLManager::~MySQLManager() {} #define MYSQL_PREFIX "mysql://" inline result parse_url(const string& url, std::map& connect_map) { - string target_url; - if(url.find(MYSQL_PREFIX) != 0) - return {ERROR_MYSQL_INVLID_URL, "Missing mysql:// at begin"}; + string target_url; + if(url.find(MYSQL_PREFIX) != 0) + return {ERROR_MYSQL_INVLID_URL, "Missing mysql:// at begin"}; - auto index_parms = url.find('?'); - if(index_parms == string::npos) { - target_url = "tcp://" + url.substr(strlen(MYSQL_PREFIX)); - } else { - target_url = "tcp://" + url.substr(strlen(MYSQL_PREFIX), index_parms - strlen(MYSQL_PREFIX)); - auto parms = url.substr(index_parms + 1); - size_t index = 0; - do { - auto idx = parms.find('&', index); - auto element = parms.substr(index, idx - index); + auto index_parms = url.find('?'); + if(index_parms == string::npos) { + target_url = "tcp://" + url.substr(strlen(MYSQL_PREFIX)); + } else { + target_url = "tcp://" + url.substr(strlen(MYSQL_PREFIX), index_parms - strlen(MYSQL_PREFIX)); + auto parms = url.substr(index_parms + 1); + size_t index = 0; + do { + auto idx = parms.find('&', index); + auto element = parms.substr(index, idx - index); - auto key_idx = element.find('='); - auto key = element.substr(0, key_idx); - auto value = element.substr(key_idx + 1); - connect_map[key] = http::decode_url(value); - logTrace(LOG_GENERAL, "Got mysql property {}. Value: {}", key, value); + auto key_idx = element.find('='); + auto key = element.substr(0, key_idx); + auto value = element.substr(key_idx + 1); + connect_map[key] = http::decode_url(value); + logTrace(LOG_GENERAL, "Got mysql property {}. Value: {}", key, value); - index = idx + 1; - } while(index != 0); - } + index = idx + 1; + } while(index != 0); + } - //if(!connect_map["hostName"].get() || strcmp(*connect_map["hostName"].get(), "")) - connect_map["hostName"] = target_url; - logTrace(LOG_GENERAL, "Got mysql property {}. Value: {}", "hostName", target_url); - return result::success; + //if(!connect_map["hostName"].get() || strcmp(*connect_map["hostName"].get(), "")) + connect_map["hostName"] = target_url; + logTrace(LOG_GENERAL, "Got mysql property {}. Value: {}", "hostName", target_url); + return result::success; } //mysql://[host][:port]/[database][?propertyName1=propertyValue1[&propertyName2=propertyValue2]...] inline bool parse_mysql_data(const string& url, string& error, string& host, uint16_t& port, string& database, map& properties) { - size_t parse_index = 0; - /* parse the scheme */ - { - auto index = url.find("://", parse_index); - if(index == -1 || url.substr(parse_index, index - parse_index) != "mysql") { - error = "missing/invalid URL scheme"; - return false; - } + size_t parse_index = 0; + /* parse the scheme */ + { + auto index = url.find("://", parse_index); + if(index == -1 || url.substr(parse_index, index - parse_index) != "mysql") { + error = "missing/invalid URL scheme"; + return false; + } - parse_index = index + 3; - if(parse_index >= url.length()) { - error = "unexpected EOL after scheme"; - return false; - } - } + parse_index = index + 3; + if(parse_index >= url.length()) { + error = "unexpected EOL after scheme"; + return false; + } + } - /* parse host[:port]*/ - { - auto index = url.find('/', parse_index); - if(index == -1) { - error = "missing host/port"; - return false; - } + /* parse host[:port]*/ + { + auto index = url.find('/', parse_index); + if(index == -1) { + error = "missing host/port"; + return false; + } - auto host_port = url.substr(parse_index, index - parse_index); + auto host_port = url.substr(parse_index, index - parse_index); - auto port_index = host_port.find(':'); - if(port_index == -1) { - host = host_port; - } else { - host = host_port.substr(0, port_index); - auto port_str = host_port.substr(port_index + 1); - try { - port = stol(port_str); - } catch(std::exception& ex) { - error = "failed to parse port"; - return false; - } - } - if(host.empty()) { - error = "host is empty"; - return false; - } + auto port_index = host_port.find(':'); + if(port_index == -1) { + host = host_port; + } else { + host = host_port.substr(0, port_index); + auto port_str = host_port.substr(port_index + 1); + try { + port = stol(port_str); + } catch(std::exception& ex) { + error = "failed to parse port"; + return false; + } + } + if(host.empty()) { + error = "host is empty"; + return false; + } - parse_index = index + 1; - if(parse_index >= url.length()) { - error = "unexpected EOL after host/port"; - return false; - } - } + parse_index = index + 1; + if(parse_index >= url.length()) { + error = "unexpected EOL after host/port"; + return false; + } + } - /* the database */ - { - auto index = url.find('?', parse_index); - if(index == -1) { - database = url.substr(parse_index); - parse_index = url.length(); - } else { - database = url.substr(parse_index, index - parse_index); - parse_index = index + 1; - } + /* the database */ + { + auto index = url.find('?', parse_index); + if(index == -1) { + database = url.substr(parse_index); + parse_index = url.length(); + } else { + database = url.substr(parse_index, index - parse_index); + parse_index = index + 1; + } - if(database.empty()) { - error = "database is empty"; - return false; - } - } + if(database.empty()) { + error = "database is empty"; + return false; + } + } - /* properties */ - string full_property, property_key, property_value; - while(parse_index < url.length()){ - /* "read" the next property */ - { - auto index = url.find('&', parse_index); /* next entry */ - if(index == -1) { - full_property = url.substr(parse_index); - parse_index = url.length(); - } else { - full_property = url.substr(parse_index, index - parse_index); - parse_index = index + 1; - } - } + /* properties */ + string full_property, property_key, property_value; + while(parse_index < url.length()){ + /* "read" the next property */ + { + auto index = url.find('&', parse_index); /* next entry */ + if(index == -1) { + full_property = url.substr(parse_index); + parse_index = url.length(); + } else { + full_property = url.substr(parse_index, index - parse_index); + parse_index = index + 1; + } + } - /* parse it */ - { - auto index = full_property.find('='); - if(index == -1) { - error = "invalid property format (missing '=')"; - return false; - } + /* parse it */ + { + auto index = full_property.find('='); + if(index == -1) { + error = "invalid property format (missing '=')"; + return false; + } - property_key = full_property.substr(0, index); - property_value = full_property.substr(index + 1); - if(property_key.empty() || property_value.empty()) { - error = "invalid property key/value (empty)"; - return false; - } + property_key = full_property.substr(0, index); + property_value = full_property.substr(index + 1); + if(property_key.empty() || property_value.empty()) { + error = "invalid property key/value (empty)"; + return false; + } - properties[property_key] = http::decode_url(property_value); - } - } - return true; + properties[property_key] = http::decode_url(property_value); + } + } + return true; } mysql::Connection::~Connection() { - { - lock_guard lock(this->used_lock); - assert(!this->used); - } + { + lock_guard lock(this->used_lock); + assert(!this->used); + } - if(this->handle) { - mysql_close(this->handle); - this->handle = nullptr; - } + if(this->handle) { + mysql_close(this->handle); + this->handle = nullptr; + } } result MySQLManager::connect(const std::string &url) { - this->disconnecting = false; - string error; + this->disconnecting = false; + string error; - map properties; - string host, database; - uint16_t port; + map properties; + string host, database; + uint16_t port; - if(!parse_mysql_data(url, error, host, port, database, properties)) { - error = "URL parsing failed: " + error; - return {ERROR_MYSQL_INVLID_URL, error}; - } + if(!parse_mysql_data(url, error, host, port, database, properties)) { + error = "URL parsing failed: " + error; + return {ERROR_MYSQL_INVLID_URL, error}; + } - size_t connections = 4; - if(properties.count("connections") > 0) { - try { - connections = stol(properties["connections"]); - } catch(std::exception& ex) { - return {ERROR_MYSQL_INVLID_PROPERTIES, "could not parse connection count"}; - } - } + size_t connections = 4; + if(properties.count("connections") > 0) { + try { + connections = stol(properties["connections"]); + } catch(std::exception& ex) { + return {ERROR_MYSQL_INVLID_PROPERTIES, "could not parse connection count"}; + } + } - string username, password; - if(properties.count("userName") > 0) username = properties["userName"]; - if(properties.count("username") > 0) username = properties["username"]; - if(username.empty()) return {ERROR_MYSQL_INVLID_PROPERTIES, "missing username property"}; + string username, password; + if(properties.count("userName") > 0) username = properties["userName"]; + if(properties.count("username") > 0) username = properties["username"]; + if(username.empty()) return {ERROR_MYSQL_INVLID_PROPERTIES, "missing username property"}; - if(properties.count("password") > 0) password = properties["password"]; - if(password.empty()) return {ERROR_MYSQL_INVLID_PROPERTIES, "missing password property"}; + if(properties.count("password") > 0) password = properties["password"]; + if(password.empty()) return {ERROR_MYSQL_INVLID_PROPERTIES, "missing password property"}; - //debugMessage(LOG_GENERAL, R"([MYSQL] Starting {} connections to {}:{} with database "{}" as user "{}")", connections, host, port, database, username); + //debugMessage(LOG_GENERAL, R"([MYSQL] Starting {} connections to {}:{} with database "{}" as user "{}")", connections, host, port, database, username); - for(size_t index = 0; index < connections; index++) { - auto connection = make_shared(); - connection->handle = mysql_init(nullptr); - if(!connection->handle) - return {-1, "failed to allocate connection " + to_string(index)}; + for(size_t index = 0; index < connections; index++) { + auto connection = make_shared(); + connection->handle = mysql_init(nullptr); + if(!connection->handle) + return {-1, "failed to allocate connection " + to_string(index)}; - { - my_bool reconnect = 1; - mysql_options(connection->handle, MYSQL_OPT_RECONNECT, &reconnect); - } - mysql_options(connection->handle, MYSQL_SET_CHARSET_NAME, "utf8"); - mysql_options(connection->handle, MYSQL_INIT_COMMAND, "SET NAMES utf8"); + { + my_bool reconnect = 1; + mysql_options(connection->handle, MYSQL_OPT_RECONNECT, &reconnect); + } + mysql_options(connection->handle, MYSQL_SET_CHARSET_NAME, "utf8"); + mysql_options(connection->handle, MYSQL_INIT_COMMAND, "SET NAMES utf8"); - auto result = mysql_real_connect(connection->handle, host.c_str(), username.c_str(), password.c_str(), database.c_str(), port, nullptr, 0); //CLIENT_MULTI_RESULTS | CLIENT_MULTI_STATEMENTS - if(!result) - return {-1, "failed to connect to server with connection " + to_string(index) + ": " + mysql_error(connection->handle)}; + auto result = mysql_real_connect(connection->handle, host.c_str(), username.c_str(), password.c_str(), database.c_str(), port, nullptr, 0); //CLIENT_MULTI_RESULTS | CLIENT_MULTI_STATEMENTS + if(!result) + return {-1, "failed to connect to server with connection " + to_string(index) + ": " + mysql_error(connection->handle)}; - connection->used = false; - this->connections.push_back(connection); - } + connection->used = false; + this->connections.push_back(connection); + } return result::success; } bool MySQLManager::connected() { - lock_guard lock(this->connections_lock); - return !this->connections.empty(); + lock_guard lock(this->connections_lock); + return !this->connections.empty(); } result MySQLManager::disconnect() { - lock_guard lock(this->connections_lock); - this->disconnecting = true; + lock_guard lock(this->connections_lock); + this->disconnecting = true; - this->connections.clear(); - this->connections_condition.notify_all(); + this->connections.clear(); + this->connections_condition.notify_all(); - this->disconnecting = false; - return result::success; + this->disconnecting = false; + return result::success; } struct StatementGuard { - MYSQL_STMT* stmt; + MYSQL_STMT* stmt; - ~StatementGuard() { - mysql_stmt_close(this->stmt); - } + ~StatementGuard() { + mysql_stmt_close(this->stmt); + } }; struct ResultGuard { - MYSQL_RES* result; + MYSQL_RES* result; - ~ResultGuard() { - mysql_free_result(this->result); - } + ~ResultGuard() { + mysql_free_result(this->result); + } }; template struct FreeGuard { - T* ptr; + T* ptr; - ~FreeGuard() { - if(this->ptr) ::free(this->ptr); - } + ~FreeGuard() { + if(this->ptr) ::free(this->ptr); + } }; template struct DeleteAGuard { - T* ptr; + T* ptr; - ~DeleteAGuard() { - delete[] this->ptr; - } + ~DeleteAGuard() { + delete[] this->ptr; + } }; std::shared_ptr MySQLManager::allocateCommandData() { - return make_shared(); + return make_shared(); } std::shared_ptr MySQLManager::copyCommandData(std::shared_ptr ptr) { - auto _new = this->allocateCommandData(); - _new->handle = ptr->handle; - _new->lock = ptr->lock; - _new->sql_command = ptr->sql_command; - _new->variables = ptr->variables; + auto _new = this->allocateCommandData(); + _new->handle = ptr->handle; + _new->lock = ptr->lock; + _new->sql_command = ptr->sql_command; + _new->variables = ptr->variables; - auto __new = static_pointer_cast(_new); - auto __ptr = static_pointer_cast(ptr); - //__new->stmt = __ptr->stmt; - return __new; + auto __new = static_pointer_cast(_new); + auto __ptr = static_pointer_cast(ptr); + //__new->stmt = __ptr->stmt; + return __new; } namespace sql::mysql { - bool evaluate_sql_query(string& sql, const std::vector& vars, std::vector& result) { - char quote = 0; - for(int index = 0; index < sql.length(); index++) { - if(sql[index] == '\'' || sql[index] == '"' || sql[index] == '`') { - if(quote > 0) { - if(quote == sql[index]) quote = 0; - } else { - quote = sql[index]; - } - continue; - } - if(quote > 0) continue; - if(sql[index] != ':') continue; + bool evaluate_sql_query(string& sql, const std::vector& vars, std::vector& result) { + char quote = 0; + for(int index = 0; index < sql.length(); index++) { + if(sql[index] == '\'' || sql[index] == '"' || sql[index] == '`') { + if(quote > 0) { + if(quote == sql[index]) quote = 0; + } else { + quote = sql[index]; + } + continue; + } + if(quote > 0) continue; + if(sql[index] != ':') continue; - auto index_end = sql.find_first_not_of("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_", index + 1); - if(index_end == string::npos) index_end = sql.length(); + auto index_end = sql.find_first_not_of("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_", index + 1); + if(index_end == string::npos) index_end = sql.length(); - string key = sql.substr(index, index_end - index); - //Now we can replace it with a ? - sql.replace(index, index_end - index, "?", 1); + string key = sql.substr(index, index_end - index); + //Now we can replace it with a ? + sql.replace(index, index_end - index, "?", 1); - bool insert = false; - for(const auto& e : vars) - if(e.key() == key) { - result.push_back(e); - insert = true; - break; - } - if(!insert) - result.emplace_back(); - } - return true; - } + bool insert = false; + for(const auto& e : vars) + if(e.key() == key) { + result.push_back(e); + insert = true; + break; + } + if(!insert) + result.emplace_back(); + } + return true; + } - struct BindMemory { }; + struct BindMemory { }; - /* memory must be freed via ::free! */ - bool create_bind(BindMemory*& memory, const std::vector& variables) { - size_t required_bytes = sizeof(MYSQL_BIND) * variables.size(); + /* memory must be freed via ::free! */ + bool create_bind(BindMemory*& memory, const std::vector& variables) { + size_t required_bytes = sizeof(MYSQL_BIND) * variables.size(); - /* first lets calculate the required memory */ - { - for(auto& variable : variables) { - switch (variable.type()) { - case VARTYPE_NULL: - break; - case VARTYPE_BOOLEAN: - required_bytes += sizeof(bool); - break; - case VARTYPE_INT: - required_bytes += sizeof(int32_t); - break; - case VARTYPE_LONG: - required_bytes += sizeof(int64_t); - break; - case VARTYPE_DOUBLE: - required_bytes += sizeof(double); - break; - case VARTYPE_FLOAT: - required_bytes += sizeof(float); - break; - case VARTYPE_TEXT: - //TODO: Use a direct pointer to the variable's value instead of copying it - required_bytes += sizeof(unsigned long*) + variable.value().length(); - break; - default: - return false; /* unknown variable type */ - } - } - } - if(!required_bytes) { - memory = nullptr; - return true; - } + /* first lets calculate the required memory */ + { + for(auto& variable : variables) { + switch (variable.type()) { + case VARTYPE_NULL: + break; + case VARTYPE_BOOLEAN: + required_bytes += sizeof(bool); + break; + case VARTYPE_INT: + required_bytes += sizeof(int32_t); + break; + case VARTYPE_LONG: + required_bytes += sizeof(int64_t); + break; + case VARTYPE_DOUBLE: + required_bytes += sizeof(double); + break; + case VARTYPE_FLOAT: + required_bytes += sizeof(float); + break; + case VARTYPE_TEXT: + //TODO: Use a direct pointer to the variable's value instead of copying it + required_bytes += sizeof(unsigned long*) + variable.value().length(); + break; + default: + return false; /* unknown variable type */ + } + } + } + if(!required_bytes) { + memory = nullptr; + return true; + } - //logTrace(LOG_GENERAL, "[MYSQL] Allocated {} bytes for parameters", required_bytes); - memory = (BindMemory*) malloc(required_bytes); - if(!memory) - return false; + //logTrace(LOG_GENERAL, "[MYSQL] Allocated {} bytes for parameters", required_bytes); + memory = (BindMemory*) malloc(required_bytes); + if(!memory) + return false; - memset(memory, 0, required_bytes); - /* lets fill the values */ - { - size_t memory_index = variables.size() * sizeof(MYSQL_BIND); - auto bind_ptr = (MYSQL_BIND*) memory; - auto payload_ptr = (char*) memory + sizeof(MYSQL_BIND) * variables.size(); + memset(memory, 0, required_bytes); + /* lets fill the values */ + { + size_t memory_index = variables.size() * sizeof(MYSQL_BIND); + auto bind_ptr = (MYSQL_BIND*) memory; + auto payload_ptr = (char*) memory + sizeof(MYSQL_BIND) * variables.size(); - for(size_t index = 0; index < variables.size(); index++) { - bind_ptr->buffer = payload_ptr; + for(size_t index = 0; index < variables.size(); index++) { + bind_ptr->buffer = payload_ptr; - auto& variable = variables[index]; - switch (variable.type()) { - case VARTYPE_NULL: - bind_ptr->buffer_type = enum_field_types::MYSQL_TYPE_NULL; - break; - case VARTYPE_BOOLEAN: - bind_ptr->buffer_type = enum_field_types::MYSQL_TYPE_TINY; - bind_ptr->buffer_length = sizeof(bool); - *(bool*) payload_ptr = variable.as(); - break; - case VARTYPE_INT: - bind_ptr->buffer_type = enum_field_types::MYSQL_TYPE_LONG; - bind_ptr->buffer_length = sizeof(int32_t); - *(int32_t*) payload_ptr = variable.as(); - break; - case VARTYPE_LONG: - bind_ptr->buffer_type = enum_field_types::MYSQL_TYPE_LONGLONG; - bind_ptr->buffer_length = sizeof(int64_t); - *(int64_t*) payload_ptr = variable.as(); - break; - case VARTYPE_DOUBLE: - bind_ptr->buffer_type = enum_field_types::MYSQL_TYPE_DOUBLE; - bind_ptr->buffer_length = sizeof(double); - *(double*) payload_ptr = variable.as(); - break; - case VARTYPE_FLOAT: - bind_ptr->buffer_type = enum_field_types::MYSQL_TYPE_FLOAT; - bind_ptr->buffer_length = sizeof(float); - *(float*) payload_ptr = variable.as(); - break; - case VARTYPE_TEXT: { - auto value = variable.value(); + auto& variable = variables[index]; + switch (variable.type()) { + case VARTYPE_NULL: + bind_ptr->buffer_type = enum_field_types::MYSQL_TYPE_NULL; + break; + case VARTYPE_BOOLEAN: + bind_ptr->buffer_type = enum_field_types::MYSQL_TYPE_TINY; + bind_ptr->buffer_length = sizeof(bool); + *(bool*) payload_ptr = variable.as(); + break; + case VARTYPE_INT: + bind_ptr->buffer_type = enum_field_types::MYSQL_TYPE_LONG; + bind_ptr->buffer_length = sizeof(int32_t); + *(int32_t*) payload_ptr = variable.as(); + break; + case VARTYPE_LONG: + bind_ptr->buffer_type = enum_field_types::MYSQL_TYPE_LONGLONG; + bind_ptr->buffer_length = sizeof(int64_t); + *(int64_t*) payload_ptr = variable.as(); + break; + case VARTYPE_DOUBLE: + bind_ptr->buffer_type = enum_field_types::MYSQL_TYPE_DOUBLE; + bind_ptr->buffer_length = sizeof(double); + *(double*) payload_ptr = variable.as(); + break; + case VARTYPE_FLOAT: + bind_ptr->buffer_type = enum_field_types::MYSQL_TYPE_FLOAT; + bind_ptr->buffer_length = sizeof(float); + *(float*) payload_ptr = variable.as(); + break; + case VARTYPE_TEXT: { + auto value = variable.value(); - //TODO: Use a direct pointer to the variable's value instead of copying it - //May use a string object allocated on the memory_ptr? (Special deinit needed then!) - bind_ptr->buffer_type = enum_field_types::MYSQL_TYPE_STRING; - bind_ptr->buffer_length = value.length(); + //TODO: Use a direct pointer to the variable's value instead of copying it + //May use a string object allocated on the memory_ptr? (Special deinit needed then!) + bind_ptr->buffer_type = enum_field_types::MYSQL_TYPE_STRING; + bind_ptr->buffer_length = value.length(); - bind_ptr->length = (unsigned long*) payload_ptr; - *bind_ptr->length = bind_ptr->buffer_length; + bind_ptr->length = (unsigned long*) payload_ptr; + *bind_ptr->length = bind_ptr->buffer_length; - payload_ptr += sizeof(unsigned long*); - memory_index += sizeof(unsigned long*); + payload_ptr += sizeof(unsigned long*); + memory_index += sizeof(unsigned long*); - memcpy(payload_ptr, value.data(), value.length()); - bind_ptr->buffer = payload_ptr; - break; - } - default: - return false; /* unknown variable type */ - } + memcpy(payload_ptr, value.data(), value.length()); + bind_ptr->buffer = payload_ptr; + break; + } + default: + return false; /* unknown variable type */ + } - payload_ptr += bind_ptr->buffer_length; - bind_ptr++; - assert(memory_index <= required_bytes); - } - } + payload_ptr += bind_ptr->buffer_length; + bind_ptr++; + assert(memory_index <= required_bytes); + } + } - return true; - } + return true; + } - struct ResultBindDescriptor { - size_t primitive_size = 0; + struct ResultBindDescriptor { + size_t primitive_size = 0; - void(*destroy)(char*& /* primitive ptr */) = nullptr; - bool(*create)(const MYSQL_FIELD& /* field */, MYSQL_BIND& /* bind */, char*& /* primitive ptr */) = nullptr; + void(*destroy)(char*& /* primitive ptr */) = nullptr; + bool(*create)(const MYSQL_FIELD& /* field */, MYSQL_BIND& /* bind */, char*& /* primitive ptr */) = nullptr; - bool(*get_as_string)(MYSQL_BIND& /* bind */, std::string& /* result */) = nullptr; - }; + bool(*get_as_string)(MYSQL_BIND& /* bind */, std::string& /* result */) = nullptr; + }; - /* memory to primitive string */ - template - bool m2ps(MYSQL_BIND& bind, string& str) { - if(bind.error_value || (bind.error && *bind.error)) return false; - str = std::to_string(*(T*) bind.buffer); - return true; - } + /* memory to primitive string */ + template + bool m2ps(MYSQL_BIND& bind, string& str) { + if(bind.error_value || (bind.error && *bind.error)) return false; + str = std::to_string(*(T*) bind.buffer); + return true; + } - template - void _do_destroy_primitive(char*& primitive_ptr) { - primitive_ptr += size; - } + template + void _do_destroy_primitive(char*& primitive_ptr) { + primitive_ptr += size; + } - template - bool _do_bind_primitive(const MYSQL_FIELD&, MYSQL_BIND& bind, char*& primitive_ptr) { - bind.buffer = (void*) primitive_ptr; - bind.buffer_length = size; - bind.buffer_type = (enum_field_types) type; - primitive_ptr += size; - return true; - } + template + bool _do_bind_primitive(const MYSQL_FIELD&, MYSQL_BIND& bind, char*& primitive_ptr) { + bind.buffer = (void*) primitive_ptr; + bind.buffer_length = size; + bind.buffer_type = (enum_field_types) type; + primitive_ptr += size; + return true; + } - #define CREATE_PRIMATIVE_BIND_DESCRIPTOR(mysql_type, c_type, size) \ - case mysql_type:\ - static ResultBindDescriptor _ ##mysql_type = {\ - size,\ - _do_destroy_primitive,\ - _do_bind_primitive,\ - m2ps\ - };\ - return &_ ##mysql_type; + #define CREATE_PRIMATIVE_BIND_DESCRIPTOR(mysql_type, c_type, size) \ + case mysql_type:\ + static ResultBindDescriptor _ ##mysql_type = {\ + size,\ + _do_destroy_primitive,\ + _do_bind_primitive,\ + m2ps\ + };\ + return &_ ##mysql_type; - const ResultBindDescriptor* get_bind_descriptor(enum_field_types type) { - switch (type) { - case MYSQL_TYPE_NULL: - static ResultBindDescriptor _null = { - /* primitive_size */ 0, - /* destroy */ _do_destroy_primitive<0>, - /* create */ _do_bind_primitive, - /* get_as_string */ [](MYSQL_BIND&, string& str) { str.clear(); return true; } - }; - return &_null; - CREATE_PRIMATIVE_BIND_DESCRIPTOR(MYSQL_TYPE_TINY, int8_t, 1); - CREATE_PRIMATIVE_BIND_DESCRIPTOR(MYSQL_TYPE_SHORT, int16_t, 2); - CREATE_PRIMATIVE_BIND_DESCRIPTOR(MYSQL_TYPE_INT24, int32_t, 4); - CREATE_PRIMATIVE_BIND_DESCRIPTOR(MYSQL_TYPE_LONG, int32_t, 4); - CREATE_PRIMATIVE_BIND_DESCRIPTOR(MYSQL_TYPE_LONGLONG, int64_t, 8); - CREATE_PRIMATIVE_BIND_DESCRIPTOR(MYSQL_TYPE_DOUBLE, double, sizeof(double)); - CREATE_PRIMATIVE_BIND_DESCRIPTOR(MYSQL_TYPE_FLOAT, float, sizeof(float)); - case MYSQL_TYPE_VAR_STRING: - case MYSQL_TYPE_STRING: - case MYSQL_TYPE_BLOB: - static ResultBindDescriptor _string = { - /* we store the allocated buffer in the primitive types buffer and the length */ - /* primitive_size */ sizeof(void*) + sizeof(unsigned long*), + const ResultBindDescriptor* get_bind_descriptor(enum_field_types type) { + switch (type) { + case MYSQL_TYPE_NULL: + static ResultBindDescriptor _null = { + /* primitive_size */ 0, + /* destroy */ _do_destroy_primitive<0>, + /* create */ _do_bind_primitive, + /* get_as_string */ [](MYSQL_BIND&, string& str) { str.clear(); return true; } + }; + return &_null; + CREATE_PRIMATIVE_BIND_DESCRIPTOR(MYSQL_TYPE_TINY, int8_t, 1); + CREATE_PRIMATIVE_BIND_DESCRIPTOR(MYSQL_TYPE_SHORT, int16_t, 2); + CREATE_PRIMATIVE_BIND_DESCRIPTOR(MYSQL_TYPE_INT24, int32_t, 4); + CREATE_PRIMATIVE_BIND_DESCRIPTOR(MYSQL_TYPE_LONG, int32_t, 4); + CREATE_PRIMATIVE_BIND_DESCRIPTOR(MYSQL_TYPE_LONGLONG, int64_t, 8); + CREATE_PRIMATIVE_BIND_DESCRIPTOR(MYSQL_TYPE_DOUBLE, double, sizeof(double)); + CREATE_PRIMATIVE_BIND_DESCRIPTOR(MYSQL_TYPE_FLOAT, float, sizeof(float)); + case MYSQL_TYPE_VAR_STRING: + case MYSQL_TYPE_STRING: + case MYSQL_TYPE_BLOB: + static ResultBindDescriptor _string = { + /* we store the allocated buffer in the primitive types buffer and the length */ + /* primitive_size */ sizeof(void*) + sizeof(unsigned long*), - /* destroy */ [](char*& primitive) { - ::free(*(void**) primitive); - primitive += sizeof(void*); - primitive += sizeof(unsigned long*); - }, - /* create */ [](const MYSQL_FIELD& field, MYSQL_BIND& bind, char*& primitive) { - bind.buffer_length = field.max_length > 0 ? field.max_length : min(field.length, 5UL * 1024UL * 1024UL); - bind.buffer = malloc(bind.buffer_length); - bind.buffer_type = MYSQL_TYPE_BLOB; + /* destroy */ [](char*& primitive) { + ::free(*(void**) primitive); + primitive += sizeof(void*); + primitive += sizeof(unsigned long*); + }, + /* create */ [](const MYSQL_FIELD& field, MYSQL_BIND& bind, char*& primitive) { + bind.buffer_length = field.max_length > 0 ? field.max_length : min(field.length, 5UL * 1024UL * 1024UL); + bind.buffer = malloc(bind.buffer_length); + bind.buffer_type = MYSQL_TYPE_BLOB; - *(void**) primitive = bind.buffer; - primitive += sizeof(void*); + *(void**) primitive = bind.buffer; + primitive += sizeof(void*); - bind.length = (unsigned long*) primitive; - primitive += sizeof(unsigned long*); + bind.length = (unsigned long*) primitive; + primitive += sizeof(unsigned long*); - return bind.buffer != nullptr; - }, - /* get_as_string */ [](MYSQL_BIND& bind, std::string& result) { - auto length = bind.length ? *bind.length : bind.length_value; - result.reserve(length); - result.assign((const char*) bind.buffer, length); - return true; - } - }; - return &_string; - default: - return nullptr; - } - } + return bind.buffer != nullptr; + }, + /* get_as_string */ [](MYSQL_BIND& bind, std::string& result) { + auto length = bind.length ? *bind.length : bind.length_value; + result.reserve(length); + result.assign((const char*) bind.buffer, length); + return true; + } + }; + return &_string; + default: + return nullptr; + } + } - #undef CREATE_PRIMATIVE_BIND_DESCRIPTOR + #undef CREATE_PRIMATIVE_BIND_DESCRIPTOR - struct ResultBind { - size_t field_count = 0; - BindMemory* memory = nullptr; - const ResultBindDescriptor** descriptors = nullptr; + struct ResultBind { + size_t field_count = 0; + BindMemory* memory = nullptr; + const ResultBindDescriptor** descriptors = nullptr; - ~ResultBind() { - if(memory) { - auto memory_ptr = (char*) this->memory + (sizeof(MYSQL_BIND) * field_count); + ~ResultBind() { + if(memory) { + auto memory_ptr = (char*) this->memory + (sizeof(MYSQL_BIND) * field_count); - for(size_t index = 0; index < this->field_count; index++) - this->descriptors[index]->destroy(memory_ptr); + for(size_t index = 0; index < this->field_count; index++) + this->descriptors[index]->destroy(memory_ptr); - ::free(memory); - } - delete[] descriptors; - } + ::free(memory); + } + delete[] descriptors; + } - ResultBind(const ResultBind&) = delete; - ResultBind(ResultBind&&) = default; + ResultBind(const ResultBind&) = delete; + ResultBind(ResultBind&&) = default; - inline bool get_as_string(size_t column, string& result) { - if(!descriptors) return false; + inline bool get_as_string(size_t column, string& result) { + if(!descriptors) return false; - auto& bind_ptr = *(MYSQL_BIND*) ((char*) this->memory + sizeof(MYSQL_BIND) * column); - return this->descriptors[column]->get_as_string(bind_ptr, result); - } + auto& bind_ptr = *(MYSQL_BIND*) ((char*) this->memory + sizeof(MYSQL_BIND) * column); + return this->descriptors[column]->get_as_string(bind_ptr, result); + } - inline bool get_as_string(string* results) { - if(!descriptors) return false; + inline bool get_as_string(string* results) { + if(!descriptors) return false; - auto bind_ptr = (MYSQL_BIND*) this->memory; - for(int index = 0; index < this->field_count; index++) - if(!this->descriptors[index]->get_as_string(*bind_ptr, results[index])) - return false; - else - bind_ptr++; - return true; - } - }; + auto bind_ptr = (MYSQL_BIND*) this->memory; + for(int index = 0; index < this->field_count; index++) + if(!this->descriptors[index]->get_as_string(*bind_ptr, results[index])) + return false; + else + bind_ptr++; + return true; + } + }; - bool create_result_bind(size_t field_count, MYSQL_FIELD* fields, ResultBind& result) { - size_t required_bytes = sizeof(MYSQL_BIND) * field_count; + bool create_result_bind(size_t field_count, MYSQL_FIELD* fields, ResultBind& result) { + size_t required_bytes = sizeof(MYSQL_BIND) * field_count; - assert(!result.field_count); - assert(!result.descriptors); - assert(!result.memory); - result.descriptors = new const ResultBindDescriptor*[field_count]; - result.field_count = field_count; + assert(!result.field_count); + assert(!result.descriptors); + assert(!result.memory); + result.descriptors = new const ResultBindDescriptor*[field_count]; + result.field_count = field_count; - for(size_t index = 0; index < field_count; index++) { - result.descriptors[index] = get_bind_descriptor(fields[index].type); - if(!result.descriptors[index]) return false; + for(size_t index = 0; index < field_count; index++) { + result.descriptors[index] = get_bind_descriptor(fields[index].type); + if(!result.descriptors[index]) return false; - required_bytes += result.descriptors[index]->primitive_size; - } + required_bytes += result.descriptors[index]->primitive_size; + } - if(!required_bytes) { - result.memory = nullptr; - return true; - } + if(!required_bytes) { + result.memory = nullptr; + return true; + } - //logTrace(LOG_GENERAL, "[MYSQL] Allocated {} bytes for response", required_bytes); - result.memory = (BindMemory*) malloc(required_bytes); - if(!result.memory) - return false; + //logTrace(LOG_GENERAL, "[MYSQL] Allocated {} bytes for response", required_bytes); + result.memory = (BindMemory*) malloc(required_bytes); + if(!result.memory) + return false; - memset(result.memory, 0, required_bytes); - auto memory_ptr = (char*) result.memory + (sizeof(MYSQL_BIND) * field_count); - auto bind_ptr = (MYSQL_BIND*) result.memory; - for(size_t index = 0; index < field_count; index++) { - if(!result.descriptors[index]->create(fields[index], *bind_ptr, memory_ptr)) return false; - bind_ptr->buffer_type = fields[index].type; - bind_ptr++; - } - assert(memory_ptr == ((char*) result.memory + required_bytes)); /* Overflow check */ - return true; - } - } + memset(result.memory, 0, required_bytes); + auto memory_ptr = (char*) result.memory + (sizeof(MYSQL_BIND) * field_count); + auto bind_ptr = (MYSQL_BIND*) result.memory; + for(size_t index = 0; index < field_count; index++) { + if(!result.descriptors[index]->create(fields[index], *bind_ptr, memory_ptr)) return false; + bind_ptr->buffer_type = fields[index].type; + bind_ptr++; + } + assert(memory_ptr == ((char*) result.memory + required_bytes)); /* Overflow check */ + return true; + } + } AcquiredConnection::AcquiredConnection(MySQLManager* owner, std::shared_ptr connection) : owner(owner), connection(std::move(connection)) { } AcquiredConnection::~AcquiredConnection() { - { - lock_guard lock{this->connection->used_lock}; - this->connection->used = false; - } + { + lock_guard lock{this->connection->used_lock}; + this->connection->used = false; + } - { - lock_guard lock(this->owner->connections_lock); - this->owner->connections_condition.notify_one(); - } + { + lock_guard lock(this->owner->connections_lock); + this->owner->connections_condition.notify_one(); + } } std::unique_ptr MySQLManager::next_connection() { - unique_ptr result; - { - unique_lock connections_lock(this->connections_lock); + unique_ptr result; + { + unique_lock connections_lock(this->connections_lock); - while(!result) { - size_t available_connections = 0; - for(const auto& connection : this->connections) { - available_connections++; + while(!result) { + size_t available_connections = 0; + for(const auto& connection : this->connections) { + available_connections++; - { - lock_guard use_lock(connection->used_lock); - if(connection->used) continue; - connection->used = true; - } + { + lock_guard use_lock(connection->used_lock); + if(connection->used) continue; + connection->used = true; + } - result = std::make_unique(this, connection); - break; - } + result = std::make_unique(this, connection); + break; + } - if(!result) { - if(available_connections == 0) { - if(this->listener_disconnected) - this->listener_disconnected(false); - this->disconnect(); - return nullptr; - } + if(!result) { + if(available_connections == 0) { + if(this->listener_disconnected) + this->listener_disconnected(false); + this->disconnect(); + return nullptr; + } - this->connections_condition.wait(connections_lock); /* wait for the next connection */ - } - } - } + this->connections_condition.wait(connections_lock); /* wait for the next connection */ + } + } + } //TODO: Test if the connection hasn't been used for a longer while if so use mysql_ping() to verify the connection return result; } void MySQLManager::connection_closed(const std::shared_ptr &connection) { - bool call_disconnect = false; - { - unique_lock connections_lock(this->connections_lock); - auto index = find(this->connections.begin(), this->connections.end(), connection); - if(index == this->connections.end()) return; + bool call_disconnect = false; + { + unique_lock connections_lock(this->connections_lock); + auto index = find(this->connections.begin(), this->connections.end(), connection); + if(index == this->connections.end()) return; - this->connections.erase(index); - call_disconnect = this->connections.empty(); - } + this->connections.erase(index); + call_disconnect = this->connections.empty(); + } - auto dl = this->listener_disconnected; - if(call_disconnect && dl) - dl(this->disconnecting); + auto dl = this->listener_disconnected; + if(call_disconnect && dl) + dl(this->disconnecting); } result MySQLManager::executeCommand(std::shared_ptr _ptr) { - auto ptr = static_pointer_cast(_ptr); - if(!ptr) { return {-1, "invalid command handle"}; } + auto ptr = static_pointer_cast(_ptr); + if(!ptr) { return {-1, "invalid command handle"}; } - std::lock_guard lock(ptr->lock); - auto command = ptr->sql_command; + std::lock_guard lock(ptr->lock); + auto command = ptr->sql_command; - auto variables = ptr->variables; - vector mapped_variables; - if(!sql::mysql::evaluate_sql_query(command, variables, mapped_variables)) - return {ptr->sql_command, -1, "Could not map sqlite vars to mysql!"}; + auto variables = ptr->variables; + vector mapped_variables; + if(!sql::mysql::evaluate_sql_query(command, variables, mapped_variables)) + return {ptr->sql_command, -1, "Could not map sqlite vars to mysql!"}; - FreeGuard bind_parameter_memory{nullptr}; - if(!sql::mysql::create_bind(bind_parameter_memory.ptr, mapped_variables)) - return {ptr->sql_command, -1, "Failed to allocate bind memory!"}; + FreeGuard bind_parameter_memory{nullptr}; + if(!sql::mysql::create_bind(bind_parameter_memory.ptr, mapped_variables)) + return {ptr->sql_command, -1, "Failed to allocate bind memory!"}; - ResultBind bind_result_data{0, nullptr, nullptr}; + ResultBind bind_result_data{0, nullptr, nullptr}; - auto connection = this->next_connection(); - if(!connection) return {ptr->sql_command, -1, "Could not get a valid connection!"}; + auto connection = this->next_connection(); + if(!connection) return {ptr->sql_command, -1, "Could not get a valid connection!"}; - StatementGuard stmt_guard{mysql_stmt_init(connection->connection->handle)}; - if(!stmt_guard.stmt) - return {ptr->sql_command, -1, "failed to allocate statement"}; + StatementGuard stmt_guard{mysql_stmt_init(connection->connection->handle)}; + if(!stmt_guard.stmt) + return {ptr->sql_command, -1, "failed to allocate statement"}; - if(mysql_stmt_prepare(stmt_guard.stmt, command.c_str(), command.length())) { - auto errc = mysql_stmt_errno(stmt_guard.stmt); - if(errc == CR_SERVER_GONE_ERROR || errc == CR_SERVER_LOST || errc == CR_CONNECTION_ERROR) - this->connection_closed(connection->connection); + if(mysql_stmt_prepare(stmt_guard.stmt, command.c_str(), command.length())) { + auto errc = mysql_stmt_errno(stmt_guard.stmt); + if(errc == CR_SERVER_GONE_ERROR || errc == CR_SERVER_LOST || errc == CR_CONNECTION_ERROR) + this->connection_closed(connection->connection); - return {ptr->sql_command, -1, "failed to prepare statement: " + string(mysql_stmt_error(stmt_guard.stmt))}; - } + return {ptr->sql_command, -1, "failed to prepare statement: " + string(mysql_stmt_error(stmt_guard.stmt))}; + } - /* validate all parameters */ - auto parameter_count = mysql_stmt_param_count(stmt_guard.stmt); - if(parameter_count != mapped_variables.size()) - return {ptr->sql_command, -1, "invalid parameter count. Statement contains " + to_string(parameter_count) + " parameters but only " + to_string(mapped_variables.size()) + " are given."}; + /* validate all parameters */ + auto parameter_count = mysql_stmt_param_count(stmt_guard.stmt); + if(parameter_count != mapped_variables.size()) + return {ptr->sql_command, -1, "invalid parameter count. Statement contains " + to_string(parameter_count) + " parameters but only " + to_string(mapped_variables.size()) + " are given."}; - if(bind_parameter_memory.ptr) { - if(mysql_stmt_bind_param(stmt_guard.stmt, (MYSQL_BIND*) bind_parameter_memory.ptr)) - return {ptr->sql_command, -1, "failed to bind parameters to statement: " + string(mysql_stmt_error(stmt_guard.stmt))}; - } else if(parameter_count > 0) - return {ptr->sql_command, -1, "invalid parameter count. Statement contains " + to_string(parameter_count) + " parameters but only " + to_string(mapped_variables.size()) + " are given (bind nullptr)."}; + if(bind_parameter_memory.ptr) { + if(mysql_stmt_bind_param(stmt_guard.stmt, (MYSQL_BIND*) bind_parameter_memory.ptr)) + return {ptr->sql_command, -1, "failed to bind parameters to statement: " + string(mysql_stmt_error(stmt_guard.stmt))}; + } else if(parameter_count > 0) + return {ptr->sql_command, -1, "invalid parameter count. Statement contains " + to_string(parameter_count) + " parameters but only " + to_string(mapped_variables.size()) + " are given (bind nullptr)."}; - if(mysql_stmt_execute(stmt_guard.stmt)) { - auto errc = mysql_stmt_errno(stmt_guard.stmt); - if(errc == CR_SERVER_GONE_ERROR || errc == CR_SERVER_LOST || errc == CR_CONNECTION_ERROR) - this->connection_closed(connection->connection); + if(mysql_stmt_execute(stmt_guard.stmt)) { + auto errc = mysql_stmt_errno(stmt_guard.stmt); + if(errc == CR_SERVER_GONE_ERROR || errc == CR_SERVER_LOST || errc == CR_CONNECTION_ERROR) + this->connection_closed(connection->connection); - return {ptr->sql_command, -1, "failed to execute query statement: " + string(mysql_stmt_error(stmt_guard.stmt))}; - } + return {ptr->sql_command, -1, "failed to execute query statement: " + string(mysql_stmt_error(stmt_guard.stmt))}; + } - return result::success; + return result::success; } result MySQLManager::queryCommand(shared_ptr _ptr, const QueryCallback &fn) { - auto ptr = static_pointer_cast(_ptr); - if(!ptr) { return {-1, "invalid command handle"}; } + auto ptr = static_pointer_cast(_ptr); + if(!ptr) { return {-1, "invalid command handle"}; } - std::lock_guard lock(ptr->lock); - auto command = ptr->sql_command; + std::lock_guard lock(ptr->lock); + auto command = ptr->sql_command; - auto variables = ptr->variables; - vector mapped_variables; - if(!sql::mysql::evaluate_sql_query(command, variables, mapped_variables)) return {ptr->sql_command, -1, "Could not map sqlite vars to mysql!"}; + auto variables = ptr->variables; + vector mapped_variables; + if(!sql::mysql::evaluate_sql_query(command, variables, mapped_variables)) return {ptr->sql_command, -1, "Could not map sqlite vars to mysql!"}; - FreeGuard bind_parameter_memory{nullptr}; - if(!sql::mysql::create_bind(bind_parameter_memory.ptr, mapped_variables)) return {ptr->sql_command, -1, "Failed to allocate bind memory!"}; + FreeGuard bind_parameter_memory{nullptr}; + if(!sql::mysql::create_bind(bind_parameter_memory.ptr, mapped_variables)) return {ptr->sql_command, -1, "Failed to allocate bind memory!"}; - ResultBind bind_result_data{0, nullptr, nullptr}; + ResultBind bind_result_data{0, nullptr, nullptr}; - auto connection = this->next_connection(); - if(!connection) return {ptr->sql_command, -1, "Could not get a valid connection!"}; + auto connection = this->next_connection(); + if(!connection) return {ptr->sql_command, -1, "Could not get a valid connection!"}; - StatementGuard stmt_guard{mysql_stmt_init(connection->connection->handle)}; - if(!stmt_guard.stmt) - return {ptr->sql_command, -1, "failed to allocate statement"}; + StatementGuard stmt_guard{mysql_stmt_init(connection->connection->handle)}; + if(!stmt_guard.stmt) + return {ptr->sql_command, -1, "failed to allocate statement"}; - if(mysql_stmt_prepare(stmt_guard.stmt, command.c_str(), command.length())) { - auto errc = mysql_stmt_errno(stmt_guard.stmt); - if(errc == CR_SERVER_GONE_ERROR || errc == CR_SERVER_LOST || errc == CR_CONNECTION_ERROR) - this->connection_closed(connection->connection); + if(mysql_stmt_prepare(stmt_guard.stmt, command.c_str(), command.length())) { + auto errc = mysql_stmt_errno(stmt_guard.stmt); + if(errc == CR_SERVER_GONE_ERROR || errc == CR_SERVER_LOST || errc == CR_CONNECTION_ERROR) + this->connection_closed(connection->connection); - return {ptr->sql_command, -1, "failed to prepare statement: " + string(mysql_stmt_error(stmt_guard.stmt))}; - } + return {ptr->sql_command, -1, "failed to prepare statement: " + string(mysql_stmt_error(stmt_guard.stmt))}; + } - /* validate all parameters */ - { - auto parameter_count = mysql_stmt_param_count(stmt_guard.stmt); - if(parameter_count != mapped_variables.size()) - return {ptr->sql_command, -1, "invalid parameter count. Statement contains " + to_string(parameter_count) + " parameters but only " + to_string(mapped_variables.size()) + " are given."}; - } + /* validate all parameters */ + { + auto parameter_count = mysql_stmt_param_count(stmt_guard.stmt); + if(parameter_count != mapped_variables.size()) + return {ptr->sql_command, -1, "invalid parameter count. Statement contains " + to_string(parameter_count) + " parameters but only " + to_string(mapped_variables.size()) + " are given."}; + } - if(bind_parameter_memory.ptr) { - if(mysql_stmt_bind_param(stmt_guard.stmt, (MYSQL_BIND*) bind_parameter_memory.ptr)) - return {ptr->sql_command, -1, "failed to bind parameters to statement: " + string(mysql_stmt_error(stmt_guard.stmt))}; - } + if(bind_parameter_memory.ptr) { + if(mysql_stmt_bind_param(stmt_guard.stmt, (MYSQL_BIND*) bind_parameter_memory.ptr)) + return {ptr->sql_command, -1, "failed to bind parameters to statement: " + string(mysql_stmt_error(stmt_guard.stmt))}; + } - if(mysql_stmt_execute(stmt_guard.stmt)) { - auto errc = mysql_stmt_errno(stmt_guard.stmt); - if(errc == CR_SERVER_GONE_ERROR || errc == CR_SERVER_LOST || errc == CR_CONNECTION_ERROR) - this->connection_closed(connection->connection); + if(mysql_stmt_execute(stmt_guard.stmt)) { + auto errc = mysql_stmt_errno(stmt_guard.stmt); + if(errc == CR_SERVER_GONE_ERROR || errc == CR_SERVER_LOST || errc == CR_CONNECTION_ERROR) + this->connection_closed(connection->connection); - return {ptr->sql_command, -1, "failed to execute query statement: " + string(mysql_stmt_error(stmt_guard.stmt))}; - } + return {ptr->sql_command, -1, "failed to execute query statement: " + string(mysql_stmt_error(stmt_guard.stmt))}; + } - //if(mysql_stmt_store_result(stmt_guard.stmt)) - // return {ptr->sql_command, -1, "failed to store query result: " + string(mysql_stmt_error(stmt_guard.stmt))}; + //if(mysql_stmt_store_result(stmt_guard.stmt)) + // return {ptr->sql_command, -1, "failed to store query result: " + string(mysql_stmt_error(stmt_guard.stmt))}; - ResultGuard result_guard{mysql_stmt_result_metadata(stmt_guard.stmt)}; - if(!result_guard.result) - return {ptr->sql_command, -1, "failed to query result metadata: " + string(mysql_stmt_error(stmt_guard.stmt))}; + ResultGuard result_guard{mysql_stmt_result_metadata(stmt_guard.stmt)}; + if(!result_guard.result) + return {ptr->sql_command, -1, "failed to query result metadata: " + string(mysql_stmt_error(stmt_guard.stmt))}; - auto field_count = mysql_num_fields(result_guard.result); - DeleteAGuard field_names{new string[field_count]}; - DeleteAGuard field_values{new string[field_count]}; + auto field_count = mysql_num_fields(result_guard.result); + DeleteAGuard field_names{new string[field_count]}; + DeleteAGuard field_values{new string[field_count]}; - { - auto field_meta = mysql_fetch_fields(result_guard.result); - if(!field_meta && field_count > 0) - return {ptr->sql_command, -1, "failed to fetch field meta"}; + { + auto field_meta = mysql_fetch_fields(result_guard.result); + if(!field_meta && field_count > 0) + return {ptr->sql_command, -1, "failed to fetch field meta"}; - if(!sql::mysql::create_result_bind(field_count, field_meta, bind_result_data)) - return {ptr->sql_command, -1, "failed to allocate result buffer"}; + if(!sql::mysql::create_result_bind(field_count, field_meta, bind_result_data)) + return {ptr->sql_command, -1, "failed to allocate result buffer"}; - if(mysql_stmt_bind_result(stmt_guard.stmt, (MYSQL_BIND*) bind_result_data.memory)) - return {ptr->sql_command, -1, "failed to bind response buffer to statement: " + string(mysql_stmt_error(stmt_guard.stmt))}; + if(mysql_stmt_bind_result(stmt_guard.stmt, (MYSQL_BIND*) bind_result_data.memory)) + return {ptr->sql_command, -1, "failed to bind response buffer to statement: " + string(mysql_stmt_error(stmt_guard.stmt))}; - for(size_t index = 0; index < field_count; index++) { - field_names.ptr[index] = field_meta[index].name; // field_meta cant be null because it has been checked above - //cout << field_names.ptr[index] << " - " << field_meta[index].max_length << endl; - } - } + for(size_t index = 0; index < field_count; index++) { + field_names.ptr[index] = field_meta[index].name; // field_meta cant be null because it has been checked above + //cout << field_names.ptr[index] << " - " << field_meta[index].max_length << endl; + } + } - bool user_quit = false; - int stmt_code, row_id = 0; - while(!(stmt_code = mysql_stmt_fetch(stmt_guard.stmt))) { - bind_result_data.get_as_string(field_values.ptr); + bool user_quit = false; + int stmt_code, row_id = 0; + while(!(stmt_code = mysql_stmt_fetch(stmt_guard.stmt))) { + bind_result_data.get_as_string(field_values.ptr); - if(fn(field_count, field_values.ptr, field_names.ptr) != 0) { - user_quit = true; - break; - } + if(fn(field_count, field_values.ptr, field_names.ptr) != 0) { + user_quit = true; + break; + } - row_id++; - } + row_id++; + } - if(!user_quit) { - if(stmt_code == 1) { - auto errc = mysql_stmt_errno(stmt_guard.stmt); - if(errc == CR_SERVER_GONE_ERROR || errc == CR_SERVER_LOST || errc == CR_CONNECTION_ERROR) - this->connection_closed(connection->connection); + if(!user_quit) { + if(stmt_code == 1) { + auto errc = mysql_stmt_errno(stmt_guard.stmt); + if(errc == CR_SERVER_GONE_ERROR || errc == CR_SERVER_LOST || errc == CR_CONNECTION_ERROR) + this->connection_closed(connection->connection); - return {ptr->sql_command, -1, "failed to fetch response row " + to_string(row_id) + ": " + string(mysql_stmt_error(stmt_guard.stmt))}; - } else if(stmt_code == MYSQL_NO_DATA) - ; - else if(stmt_code == MYSQL_DATA_TRUNCATED) - return {ptr->sql_command, -1, "response data has been truncated"}; - } - return result::success; + return {ptr->sql_command, -1, "failed to fetch response row " + to_string(row_id) + ": " + string(mysql_stmt_error(stmt_guard.stmt))}; + } else if(stmt_code == MYSQL_NO_DATA) + ; + else if(stmt_code == MYSQL_DATA_TRUNCATED) + return {ptr->sql_command, -1, "response data has been truncated"}; + } + return result::success; } \ No newline at end of file diff --git a/src/sql/mysql/MySQL.h b/src/sql/mysql/MySQL.h index 129db32..dc1df66 100644 --- a/src/sql/mysql/MySQL.h +++ b/src/sql/mysql/MySQL.h @@ -16,37 +16,37 @@ namespace sql { namespace mysql { - class MySQLManager; + class MySQLManager; - bool evaluate_sql_query(std::string& sql, const std::vector& vars, std::vector& result); + bool evaluate_sql_query(std::string& sql, const std::vector& vars, std::vector& result); class MySQLCommand : public CommandData { }; - struct Connection { - MYSQL* handle = nullptr; + struct Connection { + MYSQL* handle = nullptr; - spin_lock used_lock; - bool used = false; + spin_lock used_lock; + bool used = false; - ~Connection(); - }; + ~Connection(); + }; - struct AcquiredConnection { - MySQLManager* owner; - std::shared_ptr connection; + struct AcquiredConnection { + MySQLManager* owner; + std::shared_ptr connection; - AcquiredConnection(MySQLManager* owner, std::shared_ptr ); - ~AcquiredConnection(); - }; + AcquiredConnection(MySQLManager* owner, std::shared_ptr ); + ~AcquiredConnection(); + }; class MySQLManager : public SqlManager { - friend struct AcquiredConnection; + friend struct AcquiredConnection; public: - //typedef std::function&)> ListenerConnectionDisconnect; - //typedef std::function&)> ListenerConnectionCreated; + //typedef std::function&)> ListenerConnectionDisconnect; + //typedef std::function&)> ListenerConnectionCreated; - typedef std::function ListenerConnected; - typedef std::function ListenerDisconnected; + typedef std::function ListenerConnected; + typedef std::function ListenerDisconnected; MySQLManager(); virtual ~MySQLManager(); @@ -55,22 +55,22 @@ namespace sql { bool connected() override; result disconnect() override; - ListenerDisconnected listener_disconnected; + ListenerDisconnected listener_disconnected; protected: std::shared_ptr copyCommandData(std::shared_ptr ptr) override; std::shared_ptr allocateCommandData() override; result executeCommand(std::shared_ptr ptr) override; - result queryCommand(std::shared_ptr ptr, const QueryCallback &fn) override; + result queryCommand(std::shared_ptr ptr, const QueryCallback &fn) override; - public: - std::unique_ptr next_connection(); - void connection_closed(const std::shared_ptr& /* connection */); + public: + std::unique_ptr next_connection(); + void connection_closed(const std::shared_ptr& /* connection */); - std::mutex connections_lock; - std::condition_variable connections_condition; - std::deque> connections; + std::mutex connections_lock; + std::condition_variable connections_condition; + std::deque> connections; - bool disconnecting = false; + bool disconnecting = false; }; } } \ No newline at end of file diff --git a/src/sql/sqlite/SqliteSQL.cpp b/src/sql/sqlite/SqliteSQL.cpp index 7ffc11b..4f81fd8 100644 --- a/src/sql/sqlite/SqliteSQL.cpp +++ b/src/sql/sqlite/SqliteSQL.cpp @@ -12,8 +12,8 @@ SqliteManager::~SqliteManager() { } result SqliteManager::connect(const std::string &string) { - auto url = string; - if(url.find("sqlite://") == 0) url = url.substr(strlen("sqlite://")); + auto url = string; + if(url.find("sqlite://") == 0) url = url.substr(strlen("sqlite://")); auto result = sqlite3_open(url.c_str(), &this->database); if(!this->database) @@ -27,18 +27,18 @@ bool SqliteManager::connected() { result SqliteManager::disconnect() { if(!this->database) - return {"disconnect", -1, "database not open"}; + return {"disconnect", -1, "database not open"}; this->pool->threads()->wait_for(); auto result = sqlite3_close(this->database); if(result == 0) { - this->database = nullptr; - return result::success; + this->database = nullptr; + return result::success; }; return {"disconnect", -1, "Failed to close database. Code: " + to_string(result)}; } std::shared_ptr SqliteManager::allocateCommandData() { - return std::make_shared(); + return std::make_shared(); } std::shared_ptr SqliteManager::copyCommandData(std::shared_ptr ptr) { @@ -85,14 +85,14 @@ namespace sql { } std::shared_ptr SqliteManager::allocateStatement(const std::string& command) { - sqlite3_stmt* stmt; - if(sqlite3_prepare_v2(this->database, command.data(), static_cast(command.length()), &stmt, nullptr) != SQLITE_OK) - return nullptr; + sqlite3_stmt* stmt; + if(sqlite3_prepare_v2(this->database, command.data(), static_cast(command.length()), &stmt, nullptr) != SQLITE_OK) + return nullptr; - return std::shared_ptr(stmt, [](void* _ptr) { - auto _stmt = static_cast(_ptr); - if(_stmt) sqlite3_finalize(_stmt); - }); + return std::shared_ptr(stmt, [](void* _ptr) { + auto _stmt = static_cast(_ptr); + if(_stmt) sqlite3_finalize(_stmt); + }); } result SqliteManager::queryCommand(std::shared_ptr _ptr, const QueryCallback &fn) { @@ -105,10 +105,10 @@ result SqliteManager::queryCommand(std::shared_ptr _ptr, const Quer stmt = ptr->stmt; sqlite3_reset(stmt.get()); } else { - ptr->stmt = this->allocateStatement(ptr->sql_command); - if(!ptr->stmt) - return {_ptr->sql_command,1, sqlite3_errmsg(ptr->sqlHandle()->database)}; - stmt = ptr->stmt; + ptr->stmt = this->allocateStatement(ptr->sql_command); + if(!ptr->stmt) + return {_ptr->sql_command,1, sqlite3_errmsg(ptr->sqlHandle()->database)}; + stmt = ptr->stmt; } int varIndex = 0; @@ -146,16 +146,16 @@ result SqliteManager::executeCommand(std::shared_ptr _ptr) { std::lock_guard lock(ptr->lock); result res; - sqlite3_stmt* stmt; - if(ptr->stmt){ - stmt = ptr->stmt.get(); - sqlite3_reset(stmt); - } else { - ptr->stmt = this->allocateStatement(ptr->sql_command); - if(!ptr->stmt) - return {_ptr->sql_command,1, sqlite3_errmsg(ptr->sqlHandle()->database)}; - stmt = ptr->stmt.get(); - } + sqlite3_stmt* stmt; + if(ptr->stmt){ + stmt = ptr->stmt.get(); + sqlite3_reset(stmt); + } else { + ptr->stmt = this->allocateStatement(ptr->sql_command); + if(!ptr->stmt) + return {_ptr->sql_command,1, sqlite3_errmsg(ptr->sqlHandle()->database)}; + stmt = ptr->stmt.get(); + } int varIndex = 0; for(const auto& var : ptr->variables) @@ -163,7 +163,7 @@ result SqliteManager::executeCommand(std::shared_ptr _ptr) { int result = sqlite3_step(stmt); if(result == SQLITE_DONE) - return {_ptr->sql_command,0, "success"}; + return {_ptr->sql_command,0, "success"}; if(result == SQLITE_ROW) return {_ptr->sql_command,-1, "query has a result"}; return {_ptr->sql_command, 1, sqlite3_errstr(result)}; } \ No newline at end of file diff --git a/src/ssl/SSLManager.cpp b/src/ssl/SSLManager.cpp index 5c9bd44..72a7c56 100644 --- a/src/ssl/SSLManager.cpp +++ b/src/ssl/SSLManager.cpp @@ -91,352 +91,352 @@ SSLManager::SSLManager() = default; SSLManager::~SSLManager() = default; bool SSLManager::initialize() { - SSL_load_error_strings(); - OpenSSL_add_ssl_algorithms(); + SSL_load_error_strings(); + OpenSSL_add_ssl_algorithms(); - return true; + return true; } static auto ERR_TO_STRING = [](const char* err, size_t length, void* ptrTarget){ - auto target = (string*) ptrTarget; - target->resize(length); - memcpy((void *) target->data(), err, length); - return 0; + auto target = (string*) ptrTarget; + target->resize(length); + memcpy((void *) target->data(), err, length); + return 0; }; #define SSL_ERROR(message) \ do { \ - ERR_print_errors_cb(ERR_TO_STRING, &error); \ - error = (message) + error; \ - return nullptr; \ + ERR_print_errors_cb(ERR_TO_STRING, &error); \ + error = (message) + error; \ + return nullptr; \ } while(false) std::shared_ptr SSLManager::initializeContext(const std::string &context, std::string &privateKey, std::string &certificate, std::string &error, bool raw, const std::shared_ptr& generator) { - auto load = this->loadContext(privateKey, certificate, error, raw, generator); - if(!load) return nullptr; + auto load = this->loadContext(privateKey, certificate, error, raw, generator); + if(!load) return nullptr; - { - lock_guard lock{this->context_lock}; - this->contexts[context] = load; - } - if(context.find(this->web_ctx_prefix) == 0) { - lock_guard lock{this->_web_options_lock}; - this->_web_options.reset(); - } - return load; + { + lock_guard lock{this->context_lock}; + this->contexts[context] = load; + } + if(context.find(this->web_ctx_prefix) == 0) { + lock_guard lock{this->_web_options_lock}; + this->_web_options.reset(); + } + return load; } std::shared_ptr SSLManager::initializeSSLKey(const std::string &key, const std::string &rsaKey, std::string &error, bool raw) { - auto load = this->loadSSL(rsaKey, error, raw); - if(!load) return nullptr; + auto load = this->loadSSL(rsaKey, error, raw); + if(!load) return nullptr; - { - lock_guard lock{this->context_lock}; - this->rsa[key] = load; - } - return load; + { + lock_guard lock{this->context_lock}; + this->rsa[key] = load; + } + return load; } bool SSLManager::rename_context(const std::string &old_name, const std::string &new_name) { - { - lock_guard lock{this->context_lock}; - if(this->contexts.count(old_name) == 0) - return false; - auto old = std::move(this->contexts[old_name]); - this->contexts.erase(old_name); - this->contexts[new_name] = std::move(old); - } + { + lock_guard lock{this->context_lock}; + if(this->contexts.count(old_name) == 0) + return false; + auto old = std::move(this->contexts[old_name]); + this->contexts.erase(old_name); + this->contexts[new_name] = std::move(old); + } - if(old_name.find(this->web_ctx_prefix) == 0 || new_name.find(this->web_ctx_prefix) == 0) { - lock_guard lock{this->_web_options_lock}; - this->_web_options.reset(); - } - return true; + if(old_name.find(this->web_ctx_prefix) == 0 || new_name.find(this->web_ctx_prefix) == 0) { + lock_guard lock{this->_web_options_lock}; + this->_web_options.reset(); + } + return true; } bool SSLManager::unregister_context(const std::string &context) { - { - lock_guard lock{this->context_lock}; - if(this->contexts.erase(context) == 0) - return false; - } - if(context.find(this->web_ctx_prefix) == 0) { - lock_guard lock{this->_web_options_lock}; - this->_web_options.reset(); - } - return true; + { + lock_guard lock{this->context_lock}; + if(this->contexts.erase(context) == 0) + return false; + } + if(context.find(this->web_ctx_prefix) == 0) { + lock_guard lock{this->_web_options_lock}; + this->_web_options.reset(); + } + return true; } void SSLManager::unregister_web_contexts(bool default_as_well) { - { - lock_guard lock{this->context_lock}; - decltype(this->contexts) ctxs{this->contexts}; - for(auto& [key, _] : ctxs) { - if(key == this->web_ctx_prefix + "default" && !default_as_well) - continue; + { + lock_guard lock{this->context_lock}; + decltype(this->contexts) ctxs{this->contexts}; + for(auto& [key, _] : ctxs) { + if(key == this->web_ctx_prefix + "default" && !default_as_well) + continue; - (void) _; - if(key.find(this->web_ctx_prefix) == 0) { - this->contexts.erase(key); - } - } - } + (void) _; + if(key.find(this->web_ctx_prefix) == 0) { + this->contexts.erase(key); + } + } + } - lock_guard lock{this->_web_options_lock}; - this->_web_options.reset(); + lock_guard lock{this->_web_options_lock}; + this->_web_options.reset(); } EVP_PKEY* SSLGenerator::generateKey() { - auto key = std::unique_ptr(EVP_PKEY_new(), ::EVP_PKEY_free); + auto key = std::unique_ptr(EVP_PKEY_new(), ::EVP_PKEY_free); - auto rsa = RSA_new(); - auto e = std::unique_ptr(BN_new(), ::BN_free); - BN_set_word(e.get(), RSA_F4); - if(!RSA_generate_key_ex(rsa, 2048, e.get(), nullptr)) return nullptr; - EVP_PKEY_assign_RSA(key.get(), rsa); - return key.release(); + auto rsa = RSA_new(); + auto e = std::unique_ptr(BN_new(), ::BN_free); + BN_set_word(e.get(), RSA_F4); + if(!RSA_generate_key_ex(rsa, 2048, e.get(), nullptr)) return nullptr; + EVP_PKEY_assign_RSA(key.get(), rsa); + return key.release(); } X509* SSLGenerator::generateCertificate(EVP_PKEY* key) { - auto cert = X509_new(); - X509_set_pubkey(cert, key); + auto cert = X509_new(); + X509_set_pubkey(cert, key); - ASN1_INTEGER_set(X509_get_serialNumber(cert), 3); - X509_gmtime_adj(X509_get_notBefore(cert), 0); - X509_gmtime_adj(X509_get_notAfter(cert), 31536000L); + ASN1_INTEGER_set(X509_get_serialNumber(cert), 3); + X509_gmtime_adj(X509_get_notBefore(cert), 0); + X509_gmtime_adj(X509_get_notAfter(cert), 31536000L); - X509_NAME* name = nullptr; - name = X509_get_subject_name(cert); - for(const auto& subject : this->subjects) - X509_NAME_add_entry_by_txt(name, subject.first.c_str(), MBSTRING_ASC, (unsigned char *) subject.second.c_str(), subject.second.length(), -1, 0); - X509_set_subject_name(cert, name); + X509_NAME* name = nullptr; + name = X509_get_subject_name(cert); + for(const auto& subject : this->subjects) + X509_NAME_add_entry_by_txt(name, subject.first.c_str(), MBSTRING_ASC, (unsigned char *) subject.second.c_str(), subject.second.length(), -1, 0); + X509_set_subject_name(cert, name); - name = X509_get_issuer_name(cert); - for(const auto& subject : this->issues) - X509_NAME_add_entry_by_txt(name, subject.first.c_str(), MBSTRING_ASC, (unsigned char *) subject.second.c_str(), subject.second.length(), -1, 0); + name = X509_get_issuer_name(cert); + for(const auto& subject : this->issues) + X509_NAME_add_entry_by_txt(name, subject.first.c_str(), MBSTRING_ASC, (unsigned char *) subject.second.c_str(), subject.second.length(), -1, 0); - X509_set_issuer_name(cert, name); + X509_set_issuer_name(cert, name); - X509_sign(cert, key, EVP_sha512()); - return cert; + X509_sign(cert, key, EVP_sha512()); + return cert; } //TODO passwords std::shared_ptr SSLManager::loadContext(std::string &rawKey, std::string &rawCert, std::string &error, bool is_raw, const shared_ptr& generator) { - std::shared_ptr bio_certificate = nullptr; - std::shared_ptr bio_private_key = nullptr; - std::shared_ptr certificate = nullptr; - std::shared_ptr key = nullptr; - bool allow_generate_cert{false}, allow_generate_key{false}; - bool certificate_modified{false}, key_modified{false}; - std::shared_ptr context = nullptr; - std::shared_ptr result = nullptr; + std::shared_ptr bio_certificate = nullptr; + std::shared_ptr bio_private_key = nullptr; + std::shared_ptr certificate = nullptr; + std::shared_ptr key = nullptr; + bool allow_generate_cert{false}, allow_generate_key{false}; + bool certificate_modified{false}, key_modified{false}; + std::shared_ptr context = nullptr; + std::shared_ptr result = nullptr; - if(is_raw) { - if(!rawKey.empty()) { - bio_private_key = shared_ptr(BIO_new_mem_buf(rawKey.data(), rawKey.length()), ::BIO_free); + if(is_raw) { + if(!rawKey.empty()) { + bio_private_key = shared_ptr(BIO_new_mem_buf(rawKey.data(), rawKey.length()), ::BIO_free); - if(!rawCert.empty()) { - bio_certificate = shared_ptr(BIO_new_mem_buf(rawCert.data(), rawCert.length()), ::BIO_free); - } else { - allow_generate_cert = true; - } - } else { - allow_generate_cert = true; - allow_generate_key = true; - } - if(!bio_certificate) bio_certificate = shared_ptr(BIO_new(BIO_s_mem()), ::BIO_free); - if(!bio_private_key) bio_private_key = shared_ptr(BIO_new(BIO_s_mem()), ::BIO_free); - } else { - auto key_path = fs::u8path(rawKey); - auto certificate_path = fs::u8path(rawCert); + if(!rawCert.empty()) { + bio_certificate = shared_ptr(BIO_new_mem_buf(rawCert.data(), rawCert.length()), ::BIO_free); + } else { + allow_generate_cert = true; + } + } else { + allow_generate_cert = true; + allow_generate_key = true; + } + if(!bio_certificate) bio_certificate = shared_ptr(BIO_new(BIO_s_mem()), ::BIO_free); + if(!bio_private_key) bio_private_key = shared_ptr(BIO_new(BIO_s_mem()), ::BIO_free); + } else { + auto key_path = fs::u8path(rawKey); + auto certificate_path = fs::u8path(rawCert); - auto key_exists = fs::exists(key_path); - auto certificate_exists = fs::exists(certificate_path); + auto key_exists = fs::exists(key_path); + auto certificate_exists = fs::exists(certificate_path); - if(!key_exists) { - try { - if(key_path.has_parent_path()) - fs::create_directories(key_path.parent_path()); - } catch (fs::filesystem_error& ex) { - error = "failed to create keys file parent path: " + std::string{ex.what()}; - return nullptr; - } + if(!key_exists) { + try { + if(key_path.has_parent_path()) + fs::create_directories(key_path.parent_path()); + } catch (fs::filesystem_error& ex) { + error = "failed to create keys file parent path: " + std::string{ex.what()}; + return nullptr; + } - std::ofstream {key_path}; - allow_generate_key = true; - } + std::ofstream {key_path}; + allow_generate_key = true; + } - if(!certificate_exists) { - try { - if(certificate_path.has_parent_path()) - fs::create_directories(certificate_path.parent_path()); - } catch (fs::filesystem_error& ex) { - error = "failed to create certificate file parent path: " + std::string{ex.what()}; - return nullptr; - } + if(!certificate_exists) { + try { + if(certificate_path.has_parent_path()) + fs::create_directories(certificate_path.parent_path()); + } catch (fs::filesystem_error& ex) { + error = "failed to create certificate file parent path: " + std::string{ex.what()}; + return nullptr; + } - std::ofstream {certificate_path}; - allow_generate_cert = true; - } else if(!key_exists) { - error = "missing private key"; - return nullptr; - } + std::ofstream {certificate_path}; + allow_generate_cert = true; + } else if(!key_exists) { + error = "missing private key"; + return nullptr; + } - { - auto mode = allow_generate_cert ? "rw" : "r"; - bio_certificate = shared_ptr(BIO_new_file(rawCert.c_str(), mode), ::BIO_free); - if(!bio_certificate) SSL_ERROR("Could not open certificate: "); - } + { + auto mode = allow_generate_cert ? "rw" : "r"; + bio_certificate = shared_ptr(BIO_new_file(rawCert.c_str(), mode), ::BIO_free); + if(!bio_certificate) SSL_ERROR("Could not open certificate: "); + } - { - auto mode = allow_generate_key ? "rw" : "r"; - bio_private_key = shared_ptr(BIO_new_file(rawKey.c_str(), mode), ::BIO_free); - if(!bio_private_key) SSL_ERROR("Could not open key: "); - } - } + { + auto mode = allow_generate_key ? "rw" : "r"; + bio_private_key = shared_ptr(BIO_new_file(rawKey.c_str(), mode), ::BIO_free); + if(!bio_private_key) SSL_ERROR("Could not open key: "); + } + } - certificate = shared_ptr(PEM_read_bio_X509(bio_certificate.get(), nullptr, nullptr, nullptr), ::X509_free); - if(!certificate && (!generator || !allow_generate_cert)) SSL_ERROR("Could not read certificate: "); + certificate = shared_ptr(PEM_read_bio_X509(bio_certificate.get(), nullptr, nullptr, nullptr), ::X509_free); + if(!certificate && (!generator || !allow_generate_cert)) SSL_ERROR("Could not read certificate: "); - key = shared_ptr(PEM_read_bio_PrivateKey(bio_private_key.get(), nullptr, nullptr, nullptr), ::EVP_PKEY_free); - if(!key && (!generator || !allow_generate_key)) SSL_ERROR("Could not read key: "); + key = shared_ptr(PEM_read_bio_PrivateKey(bio_private_key.get(), nullptr, nullptr, nullptr), ::EVP_PKEY_free); + if(!key && (!generator || !allow_generate_key)) SSL_ERROR("Could not read key: "); - if(!key) { - key = shared_ptr(generator->generateKey(), ::EVP_PKEY_free); - key_modified = true; - } + if(!key) { + key = shared_ptr(generator->generateKey(), ::EVP_PKEY_free); + key_modified = true; + } - if(!certificate) { - certificate = shared_ptr(generator->generateCertificate(key.get()), ::X509_free); - certificate_modified = true; - } + if(!certificate) { + certificate = shared_ptr(generator->generateCertificate(key.get()), ::X509_free); + certificate_modified = true; + } - //Create context - context = shared_ptr(SSL_CTX_new(SSLv23_server_method()), ::SSL_CTX_free); - if (!context) SSL_ERROR("Could not create context: "); + //Create context + context = shared_ptr(SSL_CTX_new(SSLv23_server_method()), ::SSL_CTX_free); + if (!context) SSL_ERROR("Could not create context: "); - if (SSL_CTX_use_PrivateKey(context.get(), key.get()) <= 0) SSL_ERROR("Could not use private key: "); - if (SSL_CTX_use_certificate(context.get(), certificate.get()) <= 0) SSL_ERROR("Could not use certificate: "); + if (SSL_CTX_use_PrivateKey(context.get(), key.get()) <= 0) SSL_ERROR("Could not use private key: "); + if (SSL_CTX_use_certificate(context.get(), certificate.get()) <= 0) SSL_ERROR("Could not use certificate: "); - result = std::make_shared(); - result->context = context; - result->certificate = certificate; - result->privateKey = key; + result = std::make_shared(); + result->context = context; + result->certificate = certificate; + result->privateKey = key; - if(key_modified) { - if(!is_raw) { - bio_private_key = shared_ptr(BIO_new_file(rawKey.c_str(), "w"), ::BIO_free); - if(PEM_write_bio_PrivateKey(bio_private_key.get(), key.get(), nullptr, nullptr, 0, nullptr, nullptr) != 1) SSL_ERROR("Could not write new key: "); - } else { - bio_private_key = shared_ptr(BIO_new(BIO_s_mem()), ::BIO_free); - if(PEM_write_bio_PrivateKey(bio_private_key.get(), key.get(), nullptr, nullptr, 0, nullptr, nullptr) != 1) SSL_ERROR("Could not write new key: "); + if(key_modified) { + if(!is_raw) { + bio_private_key = shared_ptr(BIO_new_file(rawKey.c_str(), "w"), ::BIO_free); + if(PEM_write_bio_PrivateKey(bio_private_key.get(), key.get(), nullptr, nullptr, 0, nullptr, nullptr) != 1) SSL_ERROR("Could not write new key: "); + } else { + bio_private_key = shared_ptr(BIO_new(BIO_s_mem()), ::BIO_free); + if(PEM_write_bio_PrivateKey(bio_private_key.get(), key.get(), nullptr, nullptr, 0, nullptr, nullptr) != 1) SSL_ERROR("Could not write new key: "); - const uint8_t* mem_ptr{nullptr}; - size_t length{0}; - if(!BIO_mem_contents(&*bio_private_key, &mem_ptr, &length)) SSL_ERROR("Failed to get mem contents: "); - if(!mem_ptr || length < 0) SSL_ERROR("Could not get private key mem pointer/invalid length: "); - rawKey.reserve(length); - memcpy(rawKey.data(), mem_ptr, length); - } - } + const uint8_t* mem_ptr{nullptr}; + size_t length{0}; + if(!BIO_mem_contents(&*bio_private_key, &mem_ptr, &length)) SSL_ERROR("Failed to get mem contents: "); + if(!mem_ptr || length < 0) SSL_ERROR("Could not get private key mem pointer/invalid length: "); + rawKey.reserve(length); + memcpy(rawKey.data(), mem_ptr, length); + } + } - if(certificate_modified) { - if(!is_raw) { - bio_certificate = shared_ptr(BIO_new_file(rawCert.c_str(), "w"), ::BIO_free); - if(PEM_write_bio_X509(bio_certificate.get(), certificate.get()) != 1) SSL_ERROR("Could not write new certificate: "); - } else { - bio_certificate = shared_ptr(BIO_new(BIO_s_mem()), ::BIO_free); - if(PEM_write_bio_X509(bio_certificate.get(), certificate.get()) != 1) SSL_ERROR("Could not write new certificate: "); + if(certificate_modified) { + if(!is_raw) { + bio_certificate = shared_ptr(BIO_new_file(rawCert.c_str(), "w"), ::BIO_free); + if(PEM_write_bio_X509(bio_certificate.get(), certificate.get()) != 1) SSL_ERROR("Could not write new certificate: "); + } else { + bio_certificate = shared_ptr(BIO_new(BIO_s_mem()), ::BIO_free); + if(PEM_write_bio_X509(bio_certificate.get(), certificate.get()) != 1) SSL_ERROR("Could not write new certificate: "); - const uint8_t* mem_ptr{nullptr}; - size_t length{0}; - if(!BIO_mem_contents(&*bio_private_key, &mem_ptr, &length)) SSL_ERROR("Failed to get mem contents: "); - if(!mem_ptr || length < 0) SSL_ERROR("Could not get cert bio mem pointer/invalid length: "); - rawCert.reserve(length); - memcpy(rawCert.data(), mem_ptr, length); - } - } + const uint8_t* mem_ptr{nullptr}; + size_t length{0}; + if(!BIO_mem_contents(&*bio_private_key, &mem_ptr, &length)) SSL_ERROR("Failed to get mem contents: "); + if(!mem_ptr || length < 0) SSL_ERROR("Could not get cert bio mem pointer/invalid length: "); + rawCert.reserve(length); + memcpy(rawCert.data(), mem_ptr, length); + } + } - return result; + return result; } std::shared_ptr SSLManager::loadSSL(const std::string &key_data, std::string &error, bool rawData, bool readPublic) { - std::shared_ptr key_bio{nullptr}; - std::shared_ptr key{nullptr}; - auto result = make_shared(); -// SSL_CTX_set_ecdh_auto(ctx, 1); - if(rawData) { - key_bio = shared_ptr(BIO_new(BIO_s_mem()), ::BIO_free); - BIO_write(key_bio.get(), key_data.c_str(), key_data.length()); - } else { - auto key_path = fs::u8path(key_data); + std::shared_ptr key_bio{nullptr}; + std::shared_ptr key{nullptr}; + auto result = make_shared(); +// SSL_CTX_set_ecdh_auto(ctx, 1); + if(rawData) { + key_bio = shared_ptr(BIO_new(BIO_s_mem()), ::BIO_free); + BIO_write(key_bio.get(), key_data.c_str(), key_data.length()); + } else { + auto key_path = fs::u8path(key_data); - if(!fs::exists(key_path)) { - try { - if(key_path.has_parent_path()) - fs::create_directories(key_path.parent_path()); - } catch (fs::filesystem_error& error) { - logError(LOG_GENERAL, "Could not create key directory: " + string(error.what())); - } + if(!fs::exists(key_path)) { + try { + if(key_path.has_parent_path()) + fs::create_directories(key_path.parent_path()); + } catch (fs::filesystem_error& error) { + logError(LOG_GENERAL, "Could not create key directory: " + string(error.what())); + } - { - std::ofstream { key_path }; - } - } - key_bio = shared_ptr(BIO_new_file(key_data.c_str(), "r"), ::BIO_free); - if(!key_bio) SSL_ERROR("Could not load key: "); - } + { + std::ofstream { key_path }; + } + } + key_bio = shared_ptr(BIO_new_file(key_data.c_str(), "r"), ::BIO_free); + if(!key_bio) SSL_ERROR("Could not load key: "); + } - if(readPublic) - key = shared_ptr(PEM_read_bio_PUBKEY(key_bio.get(), nullptr, nullptr, nullptr), ::EVP_PKEY_free); - else - key = shared_ptr(PEM_read_bio_PrivateKey(key_bio.get(), nullptr, nullptr, nullptr), ::EVP_PKEY_free); - result->contains_private = !readPublic; - if(!key) { - if(readPublic) { - SSL_ERROR("Could not read key!"); - } else return this->loadSSL(key_data, error, rawData, true); - } + if(readPublic) + key = shared_ptr(PEM_read_bio_PUBKEY(key_bio.get(), nullptr, nullptr, nullptr), ::EVP_PKEY_free); + else + key = shared_ptr(PEM_read_bio_PrivateKey(key_bio.get(), nullptr, nullptr, nullptr), ::EVP_PKEY_free); + result->contains_private = !readPublic; + if(!key) { + if(readPublic) { + SSL_ERROR("Could not read key!"); + } else return this->loadSSL(key_data, error, rawData, true); + } - result->key = key; - return result; + result->key = key; + return result; } bool SSLManager::verifySign(const std::shared_ptr &key, const std::string &message, const std::string &sign) { - assert(key); - auto hash = digest::sha256(message); - return RSA_verify(NID_sha256, (u_char*) hash.data(), hash.length(), (u_char*) sign.data(), sign.length(), EVP_PKEY_get1_RSA(key->key.get())) == 1; + assert(key); + auto hash = digest::sha256(message); + return RSA_verify(NID_sha256, (u_char*) hash.data(), hash.length(), (u_char*) sign.data(), sign.length(), EVP_PKEY_get1_RSA(key->key.get())) == 1; } std::shared_ptr SSLManager::web_ssl_options() { - lock_guard lock(this->_web_options_lock); - if(this->_web_options || this->_web_disabled) - return this->_web_options; + lock_guard lock(this->_web_options_lock); + if(this->_web_options || this->_web_disabled) + return this->_web_options; - this->_web_options = make_shared(); - this->_web_options->type = pipes::SSL::SERVER; - this->_web_options->context_method = TLS_method(); - this->_web_options->free_unused_keypairs = false; /* we dont want our keys get removed */ + this->_web_options = make_shared(); + this->_web_options->type = pipes::SSL::SERVER; + this->_web_options->context_method = TLS_method(); + this->_web_options->free_unused_keypairs = false; /* we dont want our keys get removed */ - lock_guard ctx_lock{this->context_lock}; - for(auto& context : this->contexts) { - auto name = context.first; - if(name.length() < this->web_ctx_prefix.length()) - continue; - if(name.substr(0, this->web_ctx_prefix.length()) != this->web_ctx_prefix) - continue; + lock_guard ctx_lock{this->context_lock}; + for(auto& context : this->contexts) { + auto name = context.first; + if(name.length() < this->web_ctx_prefix.length()) + continue; + if(name.substr(0, this->web_ctx_prefix.length()) != this->web_ctx_prefix) + continue; - auto servername = context.first.substr(this->web_ctx_prefix.length()); - if(servername == "default") { - this->_web_options->default_keypair({context.second->privateKey, context.second->certificate}); - } else { - this->_web_options->servername_keys[servername] = {context.second->privateKey, context.second->certificate}; - } - } - return this->_web_options; + auto servername = context.first.substr(this->web_ctx_prefix.length()); + if(servername == "default") { + this->_web_options->default_keypair({context.second->privateKey, context.second->certificate}); + } else { + this->_web_options->servername_keys[servername] = {context.second->privateKey, context.second->certificate}; + } + } + return this->_web_options; } \ No newline at end of file diff --git a/src/ssl/SSLManager.h b/src/ssl/SSLManager.h index e26ce0d..a0c0aff 100644 --- a/src/ssl/SSLManager.h +++ b/src/ssl/SSLManager.h @@ -7,60 +7,60 @@ #include namespace ts::ssl { - struct SSLContext { - std::shared_ptr context{nullptr}; - std::shared_ptr privateKey{nullptr}; - std::shared_ptr certificate{nullptr}; - }; + struct SSLContext { + std::shared_ptr context{nullptr}; + std::shared_ptr privateKey{nullptr}; + std::shared_ptr certificate{nullptr}; + }; - struct SSLGenerator { - std::deque> subjects; - std::deque> issues; + struct SSLGenerator { + std::deque> subjects; + std::deque> issues; - EVP_PKEY* generateKey(); - X509* generateCertificate(EVP_PKEY*); - }; + EVP_PKEY* generateKey(); + X509* generateCertificate(EVP_PKEY*); + }; - struct SSLKeyPair { - bool contains_private = false; - std::shared_ptr key = nullptr; - }; + struct SSLKeyPair { + bool contains_private = false; + std::shared_ptr key = nullptr; + }; - class SSLManager { - public: - SSLManager(); - virtual ~SSLManager(); + class SSLManager { + public: + SSLManager(); + virtual ~SSLManager(); - bool initialize(); - void printDetails(); + bool initialize(); + void printDetails(); - bool unregister_context(const std::string& /* key */); - bool rename_context(const std::string& /* old key */, const std::string& /* new key */); /* if new already exists it will be dropped */ - void unregister_web_contexts(bool /* default certificate as well */); + bool unregister_context(const std::string& /* key */); + bool rename_context(const std::string& /* old key */, const std::string& /* new key */); /* if new already exists it will be dropped */ + void unregister_web_contexts(bool /* default certificate as well */); - std::shared_ptr initializeSSLKey(const std::string &key, const std::string &rsaKey, std::string &error, bool raw = false); - std::shared_ptr initializeContext(const std::string& key, std::string& privateKey, std::string& certificate, std::string& error, bool raw = false, const std::shared_ptr& = nullptr); + std::shared_ptr initializeSSLKey(const std::string &key, const std::string &rsaKey, std::string &error, bool raw = false); + std::shared_ptr initializeContext(const std::string& key, std::string& privateKey, std::string& certificate, std::string& error, bool raw = false, const std::shared_ptr& = nullptr); - std::shared_ptr getContext(const std::string& key){ return this->contexts[key]; } - std::shared_ptr getRsaKey(const std::string& key){ return this->rsa[key]; } + std::shared_ptr getContext(const std::string& key){ return this->contexts[key]; } + std::shared_ptr getRsaKey(const std::string& key){ return this->rsa[key]; } - bool verifySign(const std::shared_ptr& key, const std::string& message, const std::string& sign); + bool verifySign(const std::shared_ptr& key, const std::string& message, const std::string& sign); - void disable_web() { this->_web_disabled = true; } - std::shared_ptr web_ssl_options(); - std::shared_ptr getQueryContext() { return this->getContext("query"); } + void disable_web() { this->_web_disabled = true; } + std::shared_ptr web_ssl_options(); + std::shared_ptr getQueryContext() { return this->getContext("query"); } - private: - std::mutex context_lock{}; - std::map> contexts; - std::map> rsa; + private: + std::mutex context_lock{}; + std::map> contexts; + std::map> rsa; - const std::string web_ctx_prefix{"web_"}; - std::mutex _web_options_lock{}; - bool _web_disabled{false}; - std::shared_ptr _web_options; + const std::string web_ctx_prefix{"web_"}; + std::mutex _web_options_lock{}; + bool _web_disabled{false}; + std::shared_ptr _web_options; - std::shared_ptr loadContext(std::string& rawKey, std::string& rawCert, std::string& error, bool rawData = false, const std::shared_ptr& = nullptr); - std::shared_ptr loadSSL(const std::string &key_data, std::string &error, bool rawData = false, bool readPublic = false); - }; - } \ No newline at end of file + std::shared_ptr loadContext(std::string& rawKey, std::string& rawCert, std::string& error, bool rawData = false, const std::shared_ptr& = nullptr); + std::shared_ptr loadSSL(const std::string &key_data, std::string &error, bool rawData = false, bool readPublic = false); + }; + } \ No newline at end of file diff --git a/test/BBTest.cpp b/test/BBTest.cpp index 6d61aef..b079195 100644 --- a/test/BBTest.cpp +++ b/test/BBTest.cpp @@ -10,20 +10,20 @@ cout << "Testing '" << message << "' for " << tag << " results in " << bbcode::s using namespace std; using namespace std::chrono; int main() { - /* - auto beg = system_clock::now(); - TEST("Hello [img]World[/img]", "img"); - TEST("[img]World[/img] Hello", "img"); - TEST("[img]World[img] Hello", "img"); - TEST("[img=https://www.teaspeak.de]World[/img] Hello", "img"); - TEST("\\[img]World[/img] Hello", "img"); - TEST("[img]World[img] Hello", "img"); - TEST("[img=https://www.teaspeak.de]World[/img] Hello", "img"); - TEST("\\[img]World[/img] Hello", "img"); - TEST("[img=https://www.teaspeak.de]World[/img] Hello", "img"); - TEST("\\[img]World[/img] Hello", "img"); - auto end = system_clock::now(); - cout << "Needed nanoseconds: " << duration_cast(end - beg).count() << endl; - */ - return 0; + /* + auto beg = system_clock::now(); + TEST("Hello [img]World[/img]", "img"); + TEST("[img]World[/img] Hello", "img"); + TEST("[img]World[img] Hello", "img"); + TEST("[img=https://www.teaspeak.de]World[/img] Hello", "img"); + TEST("\\[img]World[/img] Hello", "img"); + TEST("[img]World[img] Hello", "img"); + TEST("[img=https://www.teaspeak.de]World[/img] Hello", "img"); + TEST("\\[img]World[/img] Hello", "img"); + TEST("[img=https://www.teaspeak.de]World[/img] Hello", "img"); + TEST("\\[img]World[/img] Hello", "img"); + auto end = system_clock::now(); + cout << "Needed nanoseconds: " << duration_cast(end - beg).count() << endl; + */ + return 0; } \ No newline at end of file diff --git a/test/ChannelTest.cpp b/test/ChannelTest.cpp index eb6816a..4a362a0 100644 --- a/test/ChannelTest.cpp +++ b/test/ChannelTest.cpp @@ -9,7 +9,7 @@ using namespace std::chrono; using namespace ts; struct TEntry : public ts::TreeEntry { - public: + public: TEntry(ChannelId channel_id) : channel_id(channel_id), previous_id(0) {} ChannelId channelId() const override { @@ -59,34 +59,34 @@ cout << " --------- TREE --------- " << endl; template void print_address(const T& idx) { - cout << &idx << endl; - [idx]() { - cout << &idx << endl; - }(); + cout << &idx << endl; + [idx]() { + cout << &idx << endl; + }(); } int main() { auto index = shared_ptr(); print_address(index); return 0; - /* - BasicChannelTree tree; - auto ch3 = tree.createChannel(0, 0, "test channel"); - auto ch2 = tree.createChannel(0, 0, "test channel2"); - auto ch = tree.createChannel(ch2->channelId(), 0, "test channel 2"); - tree.deleteChannelRoot(ch2); - ch2 = nullptr; - ch = nullptr; + /* + BasicChannelTree tree; + auto ch3 = tree.createChannel(0, 0, "test channel"); + auto ch2 = tree.createChannel(0, 0, "test channel2"); + auto ch = tree.createChannel(ch2->channelId(), 0, "test channel 2"); + tree.deleteChannelRoot(ch2); + ch2 = nullptr; + ch = nullptr; - threads::self::sleep_for(seconds(1)); - cout << "XX" << endl; - */ + threads::self::sleep_for(seconds(1)); + cout << "XX" << endl; + */ ChannelId channel_id_index = 0; - TreeView tree; + TreeView tree; - /* Create 10 channels */ - while(channel_id_index < 20) + /* Create 10 channels */ + while(channel_id_index < 20) assert(tree.insert_entry(make_shared(channel_id_index++))); PT @@ -117,5 +117,5 @@ int main() { PT memtrack::statistics(); } - return 0; + return 0; } \ No newline at end of file diff --git a/test/CommandTest.cpp b/test/CommandTest.cpp index 7672037..a1c7d44 100644 --- a/test/CommandTest.cpp +++ b/test/CommandTest.cpp @@ -22,125 +22,125 @@ template using trigger = ts::descriptor::trigger; void handleCommand( - ts::command& _cmd, - const cconstants::return_code::optional& return_code, - const field& key_a, - const field::optional& key_b, - const field::optional::bulked& key_c, - const trigger& switch_test + ts::command& _cmd, + const cconstants::return_code::optional& return_code, + const field& key_a, + const field::optional& key_b, + const field::optional::bulked& key_c, + const trigger& switch_test ) { - if(key_a.value() < 10) - cout << "ERROR" << endl; - auto b = key_c.as(); - string key_c_str = key_c; + if(key_a.value() < 10) + cout << "ERROR" << endl; + auto b = key_c.as(); + string key_c_str = key_c; - auto c = key_b.has_value(); + auto c = key_b.has_value(); - cout << key_c[1].value() << endl; - cout << "Return code: " << return_code.get_or("XXX") << endl; - __asm__("nop"); + cout << key_c[1].value() << endl; + cout << "Return code: " << return_code.get_or("XXX") << endl; + __asm__("nop"); } command_result test() { - return command_result{error::vs_critical}; + return command_result{error::vs_critical}; } command_result test2() { - return command_result{permission::b_virtualserver_select_godmode}; + return command_result{permission::b_virtualserver_select_godmode}; } command_result test3() { - return command_result{error::vs_critical, "unknown error"}; + return command_result{error::vs_critical, "unknown error"}; } void eval_test(command_result x) { - if(x.is_detailed()) { - cout << "Detailed!" << endl; - delete x.release_details(); - } else { - auto a = x.permission_id(); - auto b = x.error_code(); - cout << (void*) a << " - " << (void*) b << endl; - } + if(x.is_detailed()) { + cout << "Detailed!" << endl; + delete x.release_details(); + } else { + auto a = x.permission_id(); + auto b = x.error_code(); + cout << (void*) a << " - " << (void*) b << endl; + } } int main() { - //for(const auto& error : avariableErrors) - // cout << error.name << " = " << hex << "0x" << error.errorId << "," << endl; + //for(const auto& error : avariableErrors) + // cout << error.name << " = " << hex << "0x" << error.errorId << "," << endl; - eval_test(test()); - eval_test(test2()); - eval_test(test3()); - /* - ios_base::sync_with_stdio(false); // Avoids synchronization with C stdio on gcc - // (either localize both or disable sync) + eval_test(test()); + eval_test(test2()); + eval_test(test3()); + /* + ios_base::sync_with_stdio(false); // Avoids synchronization with C stdio on gcc + // (either localize both or disable sync) - wcout.imbue(locale("de_DE.ISO-8859-1")); // change default locale + wcout.imbue(locale("de_DE.ISO-8859-1")); // change default locale - //░█▀▀▀█░░░░▄█░░░░░░░░░▄█░░░░░▄█░░ - const auto message = "\221\210\200\200\200\210\221\221\221\221\204\210\221\221\221\221\221\221\221\221\221\204\210\221\221\221\221\221\204\210\221\221"; - const auto auto_message = "░█▀▀▀█░░░░▄█░░░░░░░░░▄█░░░░░▄█░░"; - cout << " -> " << message << endl; - cout << " -> " << utf8_check_is_valid(message) << endl; - cout << " -> " << utf8_check_is_valid("░█▀▀▀█░░░░▄█░░░░░░░░░▄█░░░░░▄█░░") << endl; + //░█▀▀▀█░░░░▄█░░░░░░░░░▄█░░░░░▄█░░ + const auto message = "\221\210\200\200\200\210\221\221\221\221\204\210\221\221\221\221\221\221\221\221\221\204\210\221\221\221\221\221\204\210\221\221"; + const auto auto_message = "░█▀▀▀█░░░░▄█░░░░░░░░░▄█░░░░░▄█░░"; + cout << " -> " << message << endl; + cout << " -> " << utf8_check_is_valid(message) << endl; + cout << " -> " << utf8_check_is_valid("░█▀▀▀█░░░░▄█░░░░░░░░░▄█░░░░░▄█░░") << endl; Command cmd = Command::parse("test -mapping test=░█▀▀▀█░░░░▄█░░░░░░░░░▄█░░░░░▄█░░_ -x"); cout << "Build: " << cmd.build() << endl; cout << "X: " << cmd["test"] << endl; - cout << " -> " << endl; - for(const auto& e : cmd.parms()) - cout << e << endl; - */ + cout << " -> " << endl; + for(const auto& e : cmd.parms()) + cout << e << endl; + */ - /* - auto handle = make_shared(); + /* + auto handle = make_shared(); - ts::command_entry entry(handle); - entry = 255; - cout << "Value: " << entry.as() << endl; - cout << "Value: " << entry.melt().as() << endl; + ts::command_entry entry(handle); + entry = 255; + cout << "Value: " << entry.as() << endl; + cout << "Value: " << entry.melt().as() << endl; - cout << "Str: " << entry.string() << endl; - cout << "U8: " << (int) entry.melt().as() << endl; - */ + cout << "Str: " << entry.string() << endl; + cout << "U8: " << (int) entry.melt().as() << endl; + */ - //register_function(handleCommand); + //register_function(handleCommand); - cout << sizeof(command_result) << endl; - ts::command cmd("notify"); + cout << sizeof(command_result) << endl; + ts::command cmd("notify"); - cout << ts::command::parse("test a=b ").build(ts::command::format::BRACE_ESCAPED_QUERY) << endl; - cout << ts::command::parse("test a=").build(ts::command::format::BRACE_ESCAPED_QUERY) << endl; - cout << ts::command::parse("test a").build(ts::command::format::BRACE_ESCAPED_QUERY) << endl; - cout << ts::command::parse("a=c", false).build(ts::command::format::BRACE_ESCAPED_QUERY) << endl; - cout << ts::command::parse("a=c | a=c -x", false).build(ts::command::format::BRACE_ESCAPED_QUERY) << endl; - cout << ts::command::parse("a a=c|a=c").build(ts::command::format::BRACE_ESCAPED_QUERY) << endl; - cout << ts::command::parse("a a=c a=c2 -z | -? a=c").build(ts::command::format::BRACE_ESCAPED_QUERY) << endl; + cout << ts::command::parse("test a=b ").build(ts::command::format::BRACE_ESCAPED_QUERY) << endl; + cout << ts::command::parse("test a=").build(ts::command::format::BRACE_ESCAPED_QUERY) << endl; + cout << ts::command::parse("test a").build(ts::command::format::BRACE_ESCAPED_QUERY) << endl; + cout << ts::command::parse("a=c", false).build(ts::command::format::BRACE_ESCAPED_QUERY) << endl; + cout << ts::command::parse("a=c | a=c -x", false).build(ts::command::format::BRACE_ESCAPED_QUERY) << endl; + cout << ts::command::parse("a a=c|a=c").build(ts::command::format::BRACE_ESCAPED_QUERY) << endl; + cout << ts::command::parse("a a=c a=c2 -z | -? a=c").build(ts::command::format::BRACE_ESCAPED_QUERY) << endl; - /* - * - cmd[0]["key_a"] = 2; - cmd["b"] = 3; - cmd["c"] = "Hello World"; - cmd["c"] = "Hello World" + string(); - cmd["c"] = 2; - cmd.set_trigger("test"); - cmd.set_trigger("test2"); - cout << "Key_A => " << cmd[0]["key_a"].string() << endl; - */ - cmd["key_a"] = "0"; - cmd["key_b"] = "key_b_value"; - cmd["return_code"] = "ASD"; - cmd[0]["key_c"] = "key_c_value_0"; - cmd[1]["key_c"] = "key_c_value_1"; - cmd.set_trigger("test"); + /* + * + cmd[0]["key_a"] = 2; + cmd["b"] = 3; + cmd["c"] = "Hello World"; + cmd["c"] = "Hello World" + string(); + cmd["c"] = 2; + cmd.set_trigger("test"); + cmd.set_trigger("test2"); + cout << "Key_A => " << cmd[0]["key_a"].string() << endl; + */ + cmd["key_a"] = "0"; + cmd["key_b"] = "key_b_value"; + cmd["return_code"] = "ASD"; + cmd[0]["key_c"] = "key_c_value_0"; + cmd[1]["key_c"] = "key_c_value_1"; + cmd.set_trigger("test"); - auto result = ts::descriptor::describe_function(handleCommand); + auto result = ts::descriptor::describe_function(handleCommand); - auto cmd_handler = ts::descriptor::parse_function(handleCommand); - cmd_handler->invoke(cmd); - cout << cmd.build() << endl; + auto cmd_handler = ts::descriptor::parse_function(handleCommand); + cmd_handler->invoke(cmd); + cout << cmd.build() << endl; - //auto v = ts::descriptor::entry::bulked::val; + //auto v = ts::descriptor::entry::bulked::val; return 0; } \ No newline at end of file diff --git a/test/CrashTest.cpp b/test/CrashTest.cpp index 3cf1f64..7011f96 100644 --- a/test/CrashTest.cpp +++ b/test/CrashTest.cpp @@ -7,61 +7,61 @@ using namespace std; using namespace std::chrono; inline void test(const std::string& str, const nanoseconds& expected, bool expectResult) { - string error; - auto result = period::parse(str, error); - if(expectResult) { - if(!error.empty()) { - cerr << "Test '" << str << "' failed. Got unexpected error: " << error << endl; - } else { - if(result == expected) { - cout << "Test '" << str << "' Succeed. Got expected result" << endl; - } else if(result != expected) { - cout << "Test '" << str << "' failed. Got unexpected result: " << result.count() << ". Expected: " << expected.count() << endl; - } else { - cout << "Test '" << str << "' Succeed. Got expected result" << endl; - } - } - } else { - if(error.empty()) { - cerr << "Test '" << str << "' failed. Expected error, but got success!" << endl; - } else { - cout << "Test '" << str << "' Succeed. Got expected error: " << error << endl; - } - } + string error; + auto result = period::parse(str, error); + if(expectResult) { + if(!error.empty()) { + cerr << "Test '" << str << "' failed. Got unexpected error: " << error << endl; + } else { + if(result == expected) { + cout << "Test '" << str << "' Succeed. Got expected result" << endl; + } else if(result != expected) { + cout << "Test '" << str << "' failed. Got unexpected result: " << result.count() << ". Expected: " << expected.count() << endl; + } else { + cout << "Test '" << str << "' Succeed. Got expected result" << endl; + } + } + } else { + if(error.empty()) { + cerr << "Test '" << str << "' failed. Expected error, but got success!" << endl; + } else { + cout << "Test '" << str << "' Succeed. Got expected error: " << error << endl; + } + } } int stack() { - char buffer[1]; - for(register int i = 0; i <= 32; i++) { - *(buffer + i) = 3; - *(buffer - i) = 3; - } - return buffer[0]; + char buffer[1]; + for(register int i = 0; i <= 32; i++) { + *(buffer + i) = 3; + *(buffer - i) = 3; + } + return buffer[0]; } int main(int argc, char* argv[]) { - cout << "Stack: " << stack() << endl; - terminal::install(); - auto config = make_shared(); - config->logfileLevel = spdlog::level::off; - config->terminalLevel = spdlog::level::trace; - logger::setup(config); + cout << "Stack: " << stack() << endl; + terminal::install(); + auto config = make_shared(); + config->logfileLevel = spdlog::level::off; + config->terminalLevel = spdlog::level::trace; + logger::setup(config); - test("1h", hours(1), true); - test("2h", hours(2), true); - test("30h", hours(30), true); + test("1h", hours(1), true); + test("2h", hours(2), true); + test("30h", hours(30), true); - test("30s", seconds(30), true); - test("30s?", seconds(30), false); - test("s", seconds(30), false); + test("30s", seconds(30), true); + test("30s?", seconds(30), false); + test("s", seconds(30), false); - test("1m:30s", seconds(90), true); + test("1m:30s", seconds(90), true); - logMessageFmt(false, 0, "Hello {}", "A", "B", "C"); - logTrace("Hello World"); - logTrace(0, "Hello World"); - logTrace(0, "Hello World"); - logTrace(0, "Hello {:1}", "World"); - logTraceFmt(true, 0, "Hello {:2}", "World", "Dux"); - return 0; + logMessageFmt(false, 0, "Hello {}", "A", "B", "C"); + logTrace("Hello World"); + logTrace(0, "Hello World"); + logTrace(0, "Hello World"); + logTrace(0, "Hello {:1}", "World"); + logTraceFmt(true, 0, "Hello {:2}", "World", "Dux"); + return 0; } \ No newline at end of file diff --git a/test/EndianessTest.cpp b/test/EndianessTest.cpp index 453e6ca..6ce4f2d 100644 --- a/test/EndianessTest.cpp +++ b/test/EndianessTest.cpp @@ -3,22 +3,22 @@ #include union TypeBuffer { - char buf[8]; - union { - char n8_pad[7]; - uint8_t un8; - }; - union { - char n16_pad[6]; - uint16_t un16; - }; - union { - char n32_pad[4]; - uint32_t un32; - }; - union { - uint64_t un64; - }; + char buf[8]; + union { + char n8_pad[7]; + uint8_t un8; + }; + union { + char n16_pad[6]; + uint16_t un16; + }; + union { + char n32_pad[4]; + uint32_t un32; + }; + union { + uint64_t un64; + }; }; #define _T(size, n, rn) \ @@ -32,28 +32,28 @@ assert(be2le ##size(buffer.buf) == 0x ##n) #define T64(_1, _2, _3, _4, _5, _6, _7, _8) _T(64, _1 ##_2 ##_3 ##_4 ##_5 ##_6 ##_7 ##_8, _8 ##_7 ##_6 ##_5 ##_4 ##_3 ##_2 ##_1) int main() { - TypeBuffer buffer{}; - static_assert(sizeof(buffer) == 8, ""); + TypeBuffer buffer{}; + static_assert(sizeof(buffer) == 8, ""); - T8(FF); - T8(00); - T8(AF); - T8(7F); + T8(FF); + T8(00); + T8(AF); + T8(7F); - T16(FF, 00); - T16(00, FF); - T16(7F, 8F); - T16(23, CA); + T16(FF, 00); + T16(00, FF); + T16(7F, 8F); + T16(23, CA); - T32(FF, FF, FF, FF); - T32(FF, FF, 00, FF); - T32(F0, FF, 00, 0F); - T32(F0, CF, 00, 0F); + T32(FF, FF, FF, FF); + T32(FF, FF, 00, FF); + T32(F0, FF, 00, 0F); + T32(F0, CF, 00, 0F); - T64(FF, FF, FF, FF, FF, FF, FF, FF); - T64(FF, 00, 00, 00, 00, 00, 00, 00); + T64(FF, FF, FF, FF, FF, FF, FF, FF); + T64(FF, 00, 00, 00, 00, 00, 00, 00); - T64(FF, FF, 00, FF, 00, 00, 00, 00); - T64(F0, FF, 00, 0F, AF, BF, 0F, CF); - T64(F0, CF, 00, 0F, A2, 00, 03, 22); + T64(FF, FF, 00, FF, 00, 00, 00, 00); + T64(F0, FF, 00, 0F, AF, BF, 0F, CF); + T64(F0, CF, 00, 0F, A2, 00, 03, 22); } \ No newline at end of file diff --git a/test/LinkedTest.cpp b/test/LinkedTest.cpp index 0b761fc..a2b31c5 100644 --- a/test/LinkedTest.cpp +++ b/test/LinkedTest.cpp @@ -4,26 +4,26 @@ using namespace std; int main() { - deque entries = { - linked::create_entry(0, 1, 0), - linked::create_entry(0, 2, 1), - linked::create_entry(0, 3, 3), - linked::create_entry(0, 4, 5), - linked::create_entry(0, 5, 3), - }; + deque entries = { + linked::create_entry(0, 1, 0), + linked::create_entry(0, 2, 1), + linked::create_entry(0, 3, 3), + linked::create_entry(0, 4, 5), + linked::create_entry(0, 5, 3), + }; - deque errors; - auto head = linked::build_chain(entries, errors); - if(!errors.empty()) { - cout << "got " << errors.size() << " errors" << endl; - for(const auto& error : errors) - cout << " " << error << endl; - } + deque errors; + auto head = linked::build_chain(entries, errors); + if(!errors.empty()) { + cout << "got " << errors.size() << " errors" << endl; + for(const auto& error : errors) + cout << " " << error << endl; + } - while(head) { - cout << " => " << head->entry_id << endl; - head = head->next; - } + while(head) { + cout << " => " << head->entry_id << endl; + head = head->next; + } - return 0; + return 0; } \ No newline at end of file diff --git a/test/PermissionTest.cpp b/test/PermissionTest.cpp index 29286af..58049c0 100644 --- a/test/PermissionTest.cpp +++ b/test/PermissionTest.cpp @@ -10,49 +10,49 @@ using namespace ts::permission::v2; using PermissionType = ts::permission::PermissionType; void print_permissions(PermissionManager& manager) { - { - auto permissions = manager.permissions(); - cout << "Permissions: " << permissions.size() << endl; - for(const auto& permission : permissions) { - cout << " - " << ts::permission::resolvePermissionData(std::get<0>(permission))->name + ": "; - cout << (std::get<1>(permission).flags.value_set ? to_string(std::get<1>(permission).values.value) : "no value") << " negate: " << std::get<1>(permission).flags.negate << " skip: " << std::get<1>(permission).flags.skip << " "; - cout << "chan permission: " << std::get<1>(permission).flags.channel_specific << endl; - } - } - cout << "Used memory: " << manager.used_memory() << endl; + { + auto permissions = manager.permissions(); + cout << "Permissions: " << permissions.size() << endl; + for(const auto& permission : permissions) { + cout << " - " << ts::permission::resolvePermissionData(std::get<0>(permission))->name + ": "; + cout << (std::get<1>(permission).flags.value_set ? to_string(std::get<1>(permission).values.value) : "no value") << " negate: " << std::get<1>(permission).flags.negate << " skip: " << std::get<1>(permission).flags.skip << " "; + cout << "chan permission: " << std::get<1>(permission).flags.channel_specific << endl; + } + } + cout << "Used memory: " << manager.used_memory() << endl; } void print_updates(PermissionManager& manager) { - const auto updates = manager.flush_db_updates(); - cout << "Permission updates: " << updates.size() << endl; - for(auto& update : updates) { - cout << "Permission: " << ts::permission::resolvePermissionData(update.permission)->name << "; Channel: " << update.channel_id << "; DB Ref: " << update.flag_db << endl; - cout << " value: " << (update.update_value == PermissionUpdateType::do_nothing ? "do nothing" : update.update_value == PermissionUpdateType::set_value ? "set value to " + to_string(update.values.value) : "delete") << endl; - cout << " grant: " << (update.update_grant == PermissionUpdateType::do_nothing ? "do nothing" : update.update_grant == PermissionUpdateType::set_value ? "set value to " + to_string(update.values.grant) : "delete") << endl; - } + const auto updates = manager.flush_db_updates(); + cout << "Permission updates: " << updates.size() << endl; + for(auto& update : updates) { + cout << "Permission: " << ts::permission::resolvePermissionData(update.permission)->name << "; Channel: " << update.channel_id << "; DB Ref: " << update.flag_db << endl; + cout << " value: " << (update.update_value == PermissionUpdateType::do_nothing ? "do nothing" : update.update_value == PermissionUpdateType::set_value ? "set value to " + to_string(update.values.value) : "delete") << endl; + cout << " grant: " << (update.update_grant == PermissionUpdateType::do_nothing ? "do nothing" : update.update_grant == PermissionUpdateType::set_value ? "set value to " + to_string(update.values.grant) : "delete") << endl; + } } int main() { - ts::permission::setup_permission_resolve(); - /* - * + ts::permission::setup_permission_resolve(); + /* + * Structure size of PermissionManager: 176 Structure size of PermissionContainerBulk<16>: 192 Structure size of PermissionContainer: 12 - */ - cout << "Structure size of PermissionManager: " << sizeof(PermissionManager) << endl; - cout << "Structure size of PermissionContainerBulk<16>: " << sizeof(PermissionContainerBulk<16>) << endl; - cout << "Structure size of PermissionContainer: " << sizeof(PermissionContainer) << endl; - cout << "Permissions/bulk: " << PermissionManager::PERMISSIONS_BULK_ENTRY_COUNT << ". Bulks: " << PermissionManager::BULK_COUNT << " (Max permissions: " << (PermissionManager::PERMISSIONS_BULK_ENTRY_COUNT * PermissionManager::BULK_COUNT) << "; Avl: " << (uint32_t) PermissionType::permission_id_max << ")" << endl; + */ + cout << "Structure size of PermissionManager: " << sizeof(PermissionManager) << endl; + cout << "Structure size of PermissionContainerBulk<16>: " << sizeof(PermissionContainerBulk<16>) << endl; + cout << "Structure size of PermissionContainer: " << sizeof(PermissionContainer) << endl; + cout << "Permissions/bulk: " << PermissionManager::PERMISSIONS_BULK_ENTRY_COUNT << ". Bulks: " << PermissionManager::BULK_COUNT << " (Max permissions: " << (PermissionManager::PERMISSIONS_BULK_ENTRY_COUNT * PermissionManager::BULK_COUNT) << "; Avl: " << (uint32_t) PermissionType::permission_id_max << ")" << endl; - PermissionManager manager{}; - print_permissions(manager); - manager.set_permission(PermissionType::b_client_ban_ip, {1, 0}, PermissionUpdateType::set_value, PermissionUpdateType::do_nothing); - manager.set_channel_permission(PermissionType::b_client_ban_ip, 2, {1, 0}, PermissionUpdateType::set_value, PermissionUpdateType::do_nothing); - manager.set_channel_permission(PermissionType::b_client_ban_ip, 2, {1, 0}, PermissionUpdateType::delete_value, PermissionUpdateType::do_nothing); - print_updates(manager); - //manager.set_permission(PermissionType::b_client_ban_ip, {1, 0}, PermissionUpdateType::delete_value, PermissionUpdateType::do_nothing); - //manager.cleanup(); - print_permissions(manager); - return 0; + PermissionManager manager{}; + print_permissions(manager); + manager.set_permission(PermissionType::b_client_ban_ip, {1, 0}, PermissionUpdateType::set_value, PermissionUpdateType::do_nothing); + manager.set_channel_permission(PermissionType::b_client_ban_ip, 2, {1, 0}, PermissionUpdateType::set_value, PermissionUpdateType::do_nothing); + manager.set_channel_permission(PermissionType::b_client_ban_ip, 2, {1, 0}, PermissionUpdateType::delete_value, PermissionUpdateType::do_nothing); + print_updates(manager); + //manager.set_permission(PermissionType::b_client_ban_ip, {1, 0}, PermissionUpdateType::delete_value, PermissionUpdateType::do_nothing); + //manager.cleanup(); + print_permissions(manager); + return 0; } \ No newline at end of file diff --git a/test/PropertyTest.cpp b/test/PropertyTest.cpp index 3caf2e9..724ff18 100644 --- a/test/PropertyTest.cpp +++ b/test/PropertyTest.cpp @@ -7,63 +7,63 @@ using namespace std; int main() { - assert(property::impl::validateUnique()); + assert(property::impl::validateUnique()); - cout << property::impl::info(property::VIRTUALSERVER_HOST)->name << endl; - cout << property::impl::info("virtualserver_host")->name<< endl; + cout << property::impl::info(property::VIRTUALSERVER_HOST)->name << endl; + cout << property::impl::info("virtualserver_host")->name<< endl; - Properties props; - props.register_property_type(); + Properties props; + props.register_property_type(); - cout << "X: " << property::impl::info(property::SERVERINSTANCE_QUERY_PORT)->default_value << endl; - auto property = props[property::SERVERINSTANCE_QUERY_PORT]; + cout << "X: " << property::impl::info(property::SERVERINSTANCE_QUERY_PORT)->default_value << endl; + auto property = props[property::SERVERINSTANCE_QUERY_PORT]; - cout << "Port: " << props[property::SERVERINSTANCE_QUERY_PORT].as() << endl; - props[property::SERVERINSTANCE_QUERY_PORT] = "XX"; - cout << "Port: " << props[property::SERVERINSTANCE_QUERY_PORT].as() << endl; - props[property::SERVERINSTANCE_QUERY_PORT] = 2; - cout << "Port: " << props[property::SERVERINSTANCE_QUERY_PORT].as() << endl; - cout << "Port: " << props[property::SERVERINSTANCE_QUERY_PORT].as() << endl; + cout << "Port: " << props[property::SERVERINSTANCE_QUERY_PORT].as() << endl; + props[property::SERVERINSTANCE_QUERY_PORT] = "XX"; + cout << "Port: " << props[property::SERVERINSTANCE_QUERY_PORT].as() << endl; + props[property::SERVERINSTANCE_QUERY_PORT] = 2; + cout << "Port: " << props[property::SERVERINSTANCE_QUERY_PORT].as() << endl; + cout << "Port: " << props[property::SERVERINSTANCE_QUERY_PORT].as() << endl; - { - assert(property::impl::validateInput("022222", property::TYPE_UNSIGNED_NUMBER) == true); - assert(property::impl::validateInput("000000", property::TYPE_UNSIGNED_NUMBER) == true); - assert(property::impl::validateInput("011011", property::TYPE_UNSIGNED_NUMBER) == true); + { + assert(property::impl::validateInput("022222", property::TYPE_UNSIGNED_NUMBER) == true); + assert(property::impl::validateInput("000000", property::TYPE_UNSIGNED_NUMBER) == true); + assert(property::impl::validateInput("011011", property::TYPE_UNSIGNED_NUMBER) == true); - assert(property::impl::validateInput("-022222", property::TYPE_UNSIGNED_NUMBER) == false); - assert(property::impl::validateInput(" 00000", property::TYPE_UNSIGNED_NUMBER) == false); - assert(property::impl::validateInput("01101.", property::TYPE_UNSIGNED_NUMBER) == false); + assert(property::impl::validateInput("-022222", property::TYPE_UNSIGNED_NUMBER) == false); + assert(property::impl::validateInput(" 00000", property::TYPE_UNSIGNED_NUMBER) == false); + assert(property::impl::validateInput("01101.", property::TYPE_UNSIGNED_NUMBER) == false); - assert(property::impl::validateInput("022222", property::TYPE_SIGNED_NUMBER) == true); - assert(property::impl::validateInput("000000", property::TYPE_SIGNED_NUMBER) == true); - assert(property::impl::validateInput("011011", property::TYPE_SIGNED_NUMBER) == true); - assert(property::impl::validateInput("-022222", property::TYPE_SIGNED_NUMBER) == true); - assert(property::impl::validateInput("-00000", property::TYPE_SIGNED_NUMBER) == true); + assert(property::impl::validateInput("022222", property::TYPE_SIGNED_NUMBER) == true); + assert(property::impl::validateInput("000000", property::TYPE_SIGNED_NUMBER) == true); + assert(property::impl::validateInput("011011", property::TYPE_SIGNED_NUMBER) == true); + assert(property::impl::validateInput("-022222", property::TYPE_SIGNED_NUMBER) == true); + assert(property::impl::validateInput("-00000", property::TYPE_SIGNED_NUMBER) == true); - assert(property::impl::validateInput("01101.", property::TYPE_SIGNED_NUMBER) == false); - assert(property::impl::validateInput("01-101", property::TYPE_SIGNED_NUMBER) == false); + assert(property::impl::validateInput("01101.", property::TYPE_SIGNED_NUMBER) == false); + assert(property::impl::validateInput("01-101", property::TYPE_SIGNED_NUMBER) == false); - assert(property::impl::validateInput("01101.", property::TYPE_FLOAT) == true); - assert(property::impl::validateInput("-01101.", property::TYPE_FLOAT) == true); - assert(property::impl::validateInput("-.1", property::TYPE_FLOAT) == true); - assert(property::impl::validateInput("-2.22222", property::TYPE_FLOAT) == true); + assert(property::impl::validateInput("01101.", property::TYPE_FLOAT) == true); + assert(property::impl::validateInput("-01101.", property::TYPE_FLOAT) == true); + assert(property::impl::validateInput("-.1", property::TYPE_FLOAT) == true); + assert(property::impl::validateInput("-2.22222", property::TYPE_FLOAT) == true); - assert(property::impl::validateInput("01101.-2", property::TYPE_FLOAT) == false); - assert(property::impl::validateInput("-011.01.", property::TYPE_FLOAT) == false); - assert(property::impl::validateInput("-.1-", property::TYPE_FLOAT) == false); - assert(property::impl::validateInput("-2.22222.2", property::TYPE_FLOAT) == false); - } + assert(property::impl::validateInput("01101.-2", property::TYPE_FLOAT) == false); + assert(property::impl::validateInput("-011.01.", property::TYPE_FLOAT) == false); + assert(property::impl::validateInput("-.1-", property::TYPE_FLOAT) == false); + assert(property::impl::validateInput("-2.22222.2", property::TYPE_FLOAT) == false); + } - { - TIMING_START(timings); - this_thread::sleep_for(chrono::milliseconds(100)); - TIMING_STEP(timings, "01"); - this_thread::sleep_for(chrono::milliseconds(200)); - TIMING_STEP(timings, "02"); - this_thread::sleep_for(chrono::milliseconds(50)); - TIMING_STEP(timings, "03"); - this_thread::sleep_for(chrono::milliseconds(150)); - cout << TIMING_FINISH(timings) << endl; - } + { + TIMING_START(timings); + this_thread::sleep_for(chrono::milliseconds(100)); + TIMING_STEP(timings, "01"); + this_thread::sleep_for(chrono::milliseconds(200)); + TIMING_STEP(timings, "02"); + this_thread::sleep_for(chrono::milliseconds(50)); + TIMING_STEP(timings, "03"); + this_thread::sleep_for(chrono::milliseconds(150)); + cout << TIMING_FINISH(timings) << endl; + } } \ No newline at end of file diff --git a/test/RingTest.cpp b/test/RingTest.cpp index 9a0b32c..73abf94 100644 --- a/test/RingTest.cpp +++ b/test/RingTest.cpp @@ -15,107 +15,107 @@ using namespace ts::protocol; template void print_queue(RingBuffer& buffer) { - cout << "Buffer size: " << buffer.capacity() << endl; - for(size_t index = 0; index < buffer.capacity(); index++) { - auto set = buffer.slot_set((T) index); - if(buffer.current_slot() == index) - cout << " "; - else - cout << " "; - cout << index << " => " << set; - if(set) - cout << " " << buffer.slot_value(index); - cout << endl; - } + cout << "Buffer size: " << buffer.capacity() << endl; + for(size_t index = 0; index < buffer.capacity(); index++) { + auto set = buffer.slot_set((T) index); + if(buffer.current_slot() == index) + cout << " "; + else + cout << " "; + cout << index << " => " << set; + if(set) + cout << " " << buffer.slot_value(index); + cout << endl; + } } void print_meminfo() { - auto meminfo = buffer::buffer_memory(); - printf("Used buffer bytes: %zu, Allocated buffer bytes %zu Internal: %zu. Nodes: %zu Nodes full: %zu\n", meminfo.bytes_buffer_used, meminfo.bytes_buffer, meminfo.bytes_internal, meminfo.nodes,meminfo.nodes_full); + auto meminfo = buffer::buffer_memory(); + printf("Used buffer bytes: %zu, Allocated buffer bytes %zu Internal: %zu. Nodes: %zu Nodes full: %zu\n", meminfo.bytes_buffer_used, meminfo.bytes_buffer, meminfo.bytes_internal, meminfo.nodes,meminfo.nodes_full); } void print_cleanup_memory(buffer::cleanmode::value mode) { - auto info = buffer::cleanup_buffers(mode); - printf("Cleanuped %zu, Buffer: %zu, Internal: %zu\n", info.bytes_freed_buffer + info.bytes_freed_internal, info.bytes_freed_buffer, info.bytes_freed_internal); + auto info = buffer::cleanup_buffers(mode); + printf("Cleanuped %zu, Buffer: %zu, Internal: %zu\n", info.bytes_freed_buffer + info.bytes_freed_internal, info.bytes_freed_buffer, info.bytes_freed_internal); } #define TEST_COUNT (1000000) void malloc_speedtest() { - auto alloc_begin = system_clock::now(); - deque buffers; - for(size_t i = 0; i < TEST_COUNT; i++) - buffers.push_back(buffer::allocate_buffer(((buffer::size::value) i % 3) + 1)); - auto alloc_end = system_clock::now(); - buffers.clear(); - auto free_end = system_clock::now(); - printf("Alloc: %li Free: %li\n", duration_cast(alloc_end - alloc_begin).count() / TEST_COUNT, duration_cast(free_end - alloc_end).count() / TEST_COUNT); + auto alloc_begin = system_clock::now(); + deque buffers; + for(size_t i = 0; i < TEST_COUNT; i++) + buffers.push_back(buffer::allocate_buffer(((buffer::size::value) i % 3) + 1)); + auto alloc_end = system_clock::now(); + buffers.clear(); + auto free_end = system_clock::now(); + printf("Alloc: %li Free: %li\n", duration_cast(alloc_end - alloc_begin).count() / TEST_COUNT, duration_cast(free_end - alloc_end).count() / TEST_COUNT); } int main() { /* - RingBuffer buffer; + RingBuffer buffer; - buffer.insert_index(0, 1); - buffer.insert_index(1, 2); - buffer.insert_index(2, 3); - buffer.pop_front(); - buffer.insert_index(0, 1); + buffer.insert_index(0, 1); + buffer.insert_index(1, 2); + buffer.insert_index(2, 3); + buffer.pop_front(); + buffer.insert_index(0, 1); - //assert(buffer.front_set()); + //assert(buffer.front_set()); - print_queue(buffer); - cout << " => " << buffer.current_index() << " = " << buffer.pop_front() << endl; - cout << " => " << buffer.current_index() << " = " << buffer.pop_front() << endl; - cout << " => " << buffer.current_index() << " = " << buffer.pop_front() << endl; - / - assert(buffer.accept_index(0)); - assert(buffer.accept_index(1)); - assert(!buffer.accept_index(2)); + print_queue(buffer); + cout << " => " << buffer.current_index() << " = " << buffer.pop_front() << endl; + cout << " => " << buffer.current_index() << " = " << buffer.pop_front() << endl; + cout << " => " << buffer.current_index() << " = " << buffer.pop_front() << endl; + / + assert(buffer.accept_index(0)); + assert(buffer.accept_index(1)); + assert(!buffer.accept_index(2)); - print_queue(buffer); - assert(buffer.insert_index(1, 2)); - print_queue(buffer); - assert(buffer.insert_index(0, 1)); - print_queue(buffer); - assert(!buffer.insert_index(3, 2)); - print_queue(buffer); + print_queue(buffer); + assert(buffer.insert_index(1, 2)); + print_queue(buffer); + assert(buffer.insert_index(0, 1)); + print_queue(buffer); + assert(!buffer.insert_index(3, 2)); + print_queue(buffer); - cout << buffer.pop_front() << endl; - print_queue(buffer); - assert(buffer.insert_index(2, 3)); - print_queue(buffer); - cout << buffer.pop_front() << endl; - print_queue(buffer); + cout << buffer.pop_front() << endl; + print_queue(buffer); + assert(buffer.insert_index(2, 3)); + print_queue(buffer); + cout << buffer.pop_front() << endl; + print_queue(buffer); - assert(buffer.accept_index(3)); - assert(!buffer.accept_index(4)); - assert(!buffer.accept_index(5)); - buffer.push_front(2); - buffer.push_front(1); - print_queue(buffer); + assert(buffer.accept_index(3)); + assert(!buffer.accept_index(4)); + assert(!buffer.accept_index(5)); + buffer.push_front(2); + buffer.push_front(1); + print_queue(buffer); */ /* - [2019-07-05 13:49:02] [DEBUG] 162 | [127.0.0.1:60793/Another TeaSpeak user | 1] Cant decrypt packet of type Voice. Packet ID: 65527, Estimated generation: 2, Full counter: 65536. Dropping packet. Error: memory verify failed! - [2019-07-05 13:49:02] [DEBUG] 162 | [127.0.0.1:60793/Another TeaSpeak user | 1] Cant decrypt packet of type Voice. Packet ID: 65528, Estimated generation: 2, Full counter: 65536. Dropping packet. Error: memory verify failed! - [2019-07-05 13:49:02] [DEBUG] 162 | [127.0.0.1:60793/Another TeaSpeak user | 1] Cant decrypt packet of type Voice. Packet ID: 65529, Estimated generation: 2, Full counter: 65536. Dropping packet. Error: memory verify failed! - [2019-07-05 13:49:02] [DEBUG] 162 | [127.0.0.1:60793/Another TeaSpeak user | 1] Cant decrypt packet of type Voice. Packet ID: 65530, Estimated generation: 2, Full counter: 65536. Dropping packet. Error: memory verify failed! - [2019-07-05 13:49:02] [DEBUG] 162 | [127.0.0.1:60793/Another TeaSpeak user | 1] Cant decrypt packet of type Voice. Packet ID: 65531, Estimated generation: 2, Full counter: 65536. Dropping packet. Error: memory verify failed! - [2019-07-05 13:49:02] [DEBUG] 162 | [127.0.0.1:60793/Another TeaSpeak user | 1] Cant decrypt packet of type Voice. Packet ID: 65532, Estimated generation: 2, Full counter: 65536. Dropping packet. Error: memory verify failed! - [2019-07-05 13:49:02] [DEBUG] 162 | [127.0.0.1:60793/Another TeaSpeak user | 1] Cant decrypt packet of type Voice. Packet ID: 65533, Estimated generation: 2, Full counter: 65536. Dropping packet. Error: memory verify failed! - [2019-07-05 13:49:02] [DEBUG] 162 | [127.0.0.1:60793/Another TeaSpeak user | 1] Cant decrypt packet of type Voice. Packet ID: 65534, Estimated generation: 2, Full counter: 65536. Dropping packet. Error: memory verify failed! - [2019-07-05 13:49:02] [DEBUG] 162 | [127.0.0.1:60793/Another TeaSpeak user | 1] Cant decrypt packet of type Voice. Packet ID: 65535, Estimated generation: 2, Full counter: 65536. Dropping packet. Error: memory verify failed! + [2019-07-05 13:49:02] [DEBUG] 162 | [127.0.0.1:60793/Another TeaSpeak user | 1] Cant decrypt packet of type Voice. Packet ID: 65527, Estimated generation: 2, Full counter: 65536. Dropping packet. Error: memory verify failed! + [2019-07-05 13:49:02] [DEBUG] 162 | [127.0.0.1:60793/Another TeaSpeak user | 1] Cant decrypt packet of type Voice. Packet ID: 65528, Estimated generation: 2, Full counter: 65536. Dropping packet. Error: memory verify failed! + [2019-07-05 13:49:02] [DEBUG] 162 | [127.0.0.1:60793/Another TeaSpeak user | 1] Cant decrypt packet of type Voice. Packet ID: 65529, Estimated generation: 2, Full counter: 65536. Dropping packet. Error: memory verify failed! + [2019-07-05 13:49:02] [DEBUG] 162 | [127.0.0.1:60793/Another TeaSpeak user | 1] Cant decrypt packet of type Voice. Packet ID: 65530, Estimated generation: 2, Full counter: 65536. Dropping packet. Error: memory verify failed! + [2019-07-05 13:49:02] [DEBUG] 162 | [127.0.0.1:60793/Another TeaSpeak user | 1] Cant decrypt packet of type Voice. Packet ID: 65531, Estimated generation: 2, Full counter: 65536. Dropping packet. Error: memory verify failed! + [2019-07-05 13:49:02] [DEBUG] 162 | [127.0.0.1:60793/Another TeaSpeak user | 1] Cant decrypt packet of type Voice. Packet ID: 65532, Estimated generation: 2, Full counter: 65536. Dropping packet. Error: memory verify failed! + [2019-07-05 13:49:02] [DEBUG] 162 | [127.0.0.1:60793/Another TeaSpeak user | 1] Cant decrypt packet of type Voice. Packet ID: 65533, Estimated generation: 2, Full counter: 65536. Dropping packet. Error: memory verify failed! + [2019-07-05 13:49:02] [DEBUG] 162 | [127.0.0.1:60793/Another TeaSpeak user | 1] Cant decrypt packet of type Voice. Packet ID: 65534, Estimated generation: 2, Full counter: 65536. Dropping packet. Error: memory verify failed! + [2019-07-05 13:49:02] [DEBUG] 162 | [127.0.0.1:60793/Another TeaSpeak user | 1] Cant decrypt packet of type Voice. Packet ID: 65535, Estimated generation: 2, Full counter: 65536. Dropping packet. Error: memory verify failed! */ - PacketRingBuffer buffer; - buffer.set_generation_packet(0, 65500); + PacketRingBuffer buffer; + buffer.set_generation_packet(0, 65500); - while(buffer.current_index() < 100 || (buffer.full_index() >> 16) == 0) { - buffer.push_back(nullptr); - buffer.pop_front(); - cout << buffer.full_index() << " | " << buffer.current_index() << " | " << buffer.generation(buffer.current_index()) << endl; - } - __asm__("nop"); + while(buffer.current_index() < 100 || (buffer.full_index() >> 16) == 0) { + buffer.push_back(nullptr); + buffer.pop_front(); + cout << buffer.full_index() << " | " << buffer.current_index() << " | " << buffer.generation(buffer.current_index()) << endl; + } + __asm__("nop"); } \ No newline at end of file diff --git a/test/SQLTest.cpp b/test/SQLTest.cpp index d2f6b7d..f3b3d68 100644 --- a/test/SQLTest.cpp +++ b/test/SQLTest.cpp @@ -12,53 +12,53 @@ using namespace std::chrono; int f(int i); void testCompiler() { - /* - command(nullptr, "Hello World", variable{"x", "y"}, variable{"x", "y"}, variable{"x", "y"}).query([](int length, std::string* values, std::string* names) -> int { - return 0; - }); + /* + command(nullptr, "Hello World", variable{"x", "y"}, variable{"x", "y"}, variable{"x", "y"}).query([](int length, std::string* values, std::string* names) -> int { + return 0; + }); - command(nullptr, "Hello World", variable{"x", "y"}).query([](int length, char** values, char** names) { + command(nullptr, "Hello World", variable{"x", "y"}).query([](int length, char** values, char** names) { - return 0; - }); - */ + return 0; + }); + */ - /* - //This should fail! - command(nullptr, "Hello World", variable{"x", "y"}).query([](int length, char*** values, char** names) { + /* + //This should fail! + command(nullptr, "Hello World", variable{"x", "y"}).query([](int length, char*** values, char** names) { - return 0; - }); + return 0; + }); */ - /* - command(nullptr, "Hello World", variable{"x", "y"}).query([](void*, int length, char** values, char** names) { + /* + command(nullptr, "Hello World", variable{"x", "y"}).query([](void*, int length, char** values, char** names) { - return 0; - }, (void*) nullptr); + return 0; + }, (void*) nullptr); - command(nullptr, "Hello World", variable{"x", "y"}).query([](int*, int length, std::string* values, std::string* names) { + command(nullptr, "Hello World", variable{"x", "y"}).query([](int*, int length, std::string* values, std::string* names) { - return 0; - }, nullptr); + return 0; + }, nullptr); - command(nullptr, "Hello World", variable{"x", "y"}).query([](int length, char** values, char** names) { + command(nullptr, "Hello World", variable{"x", "y"}).query([](int length, char** values, char** names) { - return 0; - }); + return 0; + }); - int d = 0; - command((SqlManager*) nullptr, std::string("Hello World")).query([](const int& data, int length, std::string* values, std::string* names) -> int { + int d = 0; + command((SqlManager*) nullptr, std::string("Hello World")).query([](const int& data, int length, std::string* values, std::string* names) -> int { - return 0; - }, (const int&) d); + return 0; + }, (const int&) d); - auto cmd = command(nullptr, "", variable{"X", "Y"}); - cmd.value({"", "b"}); - */ + auto cmd = command(nullptr, "", variable{"X", "Y"}); + cmd.value({"", "b"}); + */ { //auto lambda = [](int, string*, string*) -> int { return false; }; @@ -68,8 +68,8 @@ void testCompiler() { auto lambda = [](int, string*, int, string*, string*) -> int { return false; }; command(nullptr, "").query(lambda, 1, (string*) nullptr); } - auto lambda = [](int, int, char**, char**) -> bool { return false; }; - command(nullptr, "").query(lambda, 1); + auto lambda = [](int, int, char**, char**) -> bool { return false; }; + command(nullptr, "").query(lambda, 1); { struct ProxyClass { @@ -102,87 +102,87 @@ int main() { assert(res); #endif #if false - sql::mysql::MySQLManager manager; - sql::result res{}; - assert(res = manager.connect("mysql://localhost:3306/teaspeak?userName=root&password=markus&connections=4")); - /* - assert(res = sql::command(&manager, "CREATE TABLE IF NOT EXISTS `test` (`key` TEXT, `value` TEXT)").execute()); - cout << "Old:" << endl; - assert(res = sql::command(&manager, "SELECT * FROM `test`").query([](int length, string* names, string* values) { - cout << "Got entry: Key: " << names[0] << " Value: " << names[1] << endl; - return 0; - })); - assert(res = sql::command(&manager, "INSERT INTO `test` (`key`, `value`) VALUES (:key,:value)", variable{":key", "date"}, variable{":value", "test: " + to_string(system_clock::now().time_since_epoch().count())}).execute()); - cout << "New:" << endl; - assert(res = sql::command(&manager, "SELECT * FROM `test`").query([](int length, string* names, string* values) { - cout << "Got entry: Key: " << names[0] << " Value: " << names[1] << endl; - return 0; - })); - */ - for(int i = 0; i < 80; i++) { - assert(res = sql::command(&manager, "SHOW TABLES").query([](int length, string* names, string* values) { - //cout << "Got entry: Key: " << names[0] << ":" << length << endl; - return 0; - })); - //threads::self::sleep_for(seconds(1)); - } - sql::command(&manager, "SHOW status;").query([](int length, string* values, string* names) { - if(values[0].find("Com_stmt_") != -1) - cout << values[0] << " => " << values[1] << endl; - }); + sql::mysql::MySQLManager manager; + sql::result res{}; + assert(res = manager.connect("mysql://localhost:3306/teaspeak?userName=root&password=markus&connections=4")); + /* + assert(res = sql::command(&manager, "CREATE TABLE IF NOT EXISTS `test` (`key` TEXT, `value` TEXT)").execute()); + cout << "Old:" << endl; + assert(res = sql::command(&manager, "SELECT * FROM `test`").query([](int length, string* names, string* values) { + cout << "Got entry: Key: " << names[0] << " Value: " << names[1] << endl; + return 0; + })); + assert(res = sql::command(&manager, "INSERT INTO `test` (`key`, `value`) VALUES (:key,:value)", variable{":key", "date"}, variable{":value", "test: " + to_string(system_clock::now().time_since_epoch().count())}).execute()); + cout << "New:" << endl; + assert(res = sql::command(&manager, "SELECT * FROM `test`").query([](int length, string* names, string* values) { + cout << "Got entry: Key: " << names[0] << " Value: " << names[1] << endl; + return 0; + })); + */ + for(int i = 0; i < 80; i++) { + assert(res = sql::command(&manager, "SHOW TABLES").query([](int length, string* names, string* values) { + //cout << "Got entry: Key: " << names[0] << ":" << length << endl; + return 0; + })); + //threads::self::sleep_for(seconds(1)); + } + sql::command(&manager, "SHOW status;").query([](int length, string* values, string* names) { + if(values[0].find("Com_stmt_") != -1) + cout << values[0] << " => " << values[1] << endl; + }); - cout << " ------------------- " << endl; - for(int i = 0; i < 80; i++) { - assert(res = sql::command(&manager, "SHOW TABLES").query([](int length, string* names, string* values) { - //cout << "Got entry: Key: " << names[0] << ":" << length << endl; - return 0; - })); - //threads::self::sleep_for(seconds(1)); - } - sql::command(&manager, "SHOW status;").query([](int length, string* values, string* names) { - if(values[0].find("Com_stmt_") != -1) - cout << values[0] << " => " << values[1] << endl; - }); + cout << " ------------------- " << endl; + for(int i = 0; i < 80; i++) { + assert(res = sql::command(&manager, "SHOW TABLES").query([](int length, string* names, string* values) { + //cout << "Got entry: Key: " << names[0] << ":" << length << endl; + return 0; + })); + //threads::self::sleep_for(seconds(1)); + } + sql::command(&manager, "SHOW status;").query([](int length, string* values, string* names) { + if(values[0].find("Com_stmt_") != -1) + cout << values[0] << " => " << values[1] << endl; + }); #endif #if false - //{":hello", "world"}, {":yyyy", "xxx"}, {":numeric", 2} - sql::command((SqlManager*) nullptr, std::string("SELECT *"), {":hello", "world"}, {":numeric", 2}); + //{":hello", "world"}, {":yyyy", "xxx"}, {":numeric", 2} + sql::command((SqlManager*) nullptr, std::string("SELECT *"), {":hello", "world"}, {":numeric", 2}); #endif - sql::mysql::MySQLManager manager; - manager.listener_disconnected = [](bool x){ - cout << "Disconnect: " << x << endl; - }; + sql::mysql::MySQLManager manager; + manager.listener_disconnected = [](bool x){ + cout << "Disconnect: " << x << endl; + }; - if(!manager.connect("mysql://localhost:3306/teaspeak?userName=root&password=markus&connections=1")) { - cerr << "failed to connect" << endl; - return 1; - } + if(!manager.connect("mysql://localhost:3306/teaspeak?userName=root&password=markus&connections=1")) { + cerr << "failed to connect" << endl; + return 1; + } - /* - auto result = sql::command(&manager,"INSERT INTO `level_miner` (`username`, `a`) VALUES (:username, :value)", variable{":username", "Hello"}, variable{":value", "TEST!"}).execute(); - if(!result) cout << result.fmtStr() << endl; + /* + auto result = sql::command(&manager,"INSERT INTO `level_miner` (`username`, `a`) VALUES (:username, :value)", variable{":username", "Hello"}, variable{":value", "TEST!"}).execute(); + if(!result) cout << result.fmtStr() << endl; - while(true) { - result = sql::command(&manager, "SELECT * FROM `level_miner`").query([](int length, std::string* values, std::string* names) { - cout << "-- entry" << endl; - for(int index = 0; index < length; index++) { - cout << " " << names[index] << " => " << values[index] << endl; - } - }); - cout << result.fmtStr() << endl; - this_thread::sleep_for(chrono::seconds(1)); - } - */ + while(true) { + result = sql::command(&manager, "SELECT * FROM `level_miner`").query([](int length, std::string* values, std::string* names) { + cout << "-- entry" << endl; + for(int index = 0; index < length; index++) { + cout << " " << names[index] << " => " << values[index] << endl; + } + }); + cout << result.fmtStr() << endl; + this_thread::sleep_for(chrono::seconds(1)); + } + */ - sql::command(&manager, "SELECT `cldbid`,`firstConnect`,`connections` FROM `clients` WHERE `serverId` = :sid AND `clientUid`=:uid LIMIT 1", variable{":sid", 0}, variable{":uid", "serveradmin"}).query([&](void* cl, int length, string* values, string* names){ - for (int index = 0; index < length; index++) { - logTrace(0, "Reading client property from client database table. (Key: " + names[index] + ", Value: " + values[index] + ")"); - } - return 0; - }, (void*) nullptr); + sql::command(&manager, "SELECT `cldbid`,`firstConnect`,`connections` FROM `clients` WHERE `serverId` = :sid AND `clientUid`=:uid LIMIT 1", variable{":sid", 0}, variable{":uid", "serveradmin"}).query([&](void* cl, int length, string* values, string* names){ + for (int index = 0; index < length; index++) { + logTrace(0, "Reading client property from client database table. (Key: " + names[index] + ", Value: " + values[index] + ")"); + } + return 0; + }, (void*) nullptr); - mysql_library_end(); + mysql_library_end(); } \ No newline at end of file diff --git a/test/WSSTest.cpp b/test/WSSTest.cpp index 5f87fa4..a813004 100644 --- a/test/WSSTest.cpp +++ b/test/WSSTest.cpp @@ -17,35 +17,35 @@ using namespace std; int create_socket(int port) { - int s; - struct sockaddr_in addr; + int s; + struct sockaddr_in addr; - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - addr.sin_addr.s_addr = htonl(INADDR_ANY); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = htonl(INADDR_ANY); - s = socket(AF_INET, SOCK_STREAM, 0); - if (s < 0) { - perror("Unable to create socket"); - exit(EXIT_FAILURE); - } - int optval = 1; - if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(int)) < 0) - printf("Cannot set SO_REUSEADDR option on listen socket (%s)\n", strerror(errno)); + s = socket(AF_INET, SOCK_STREAM, 0); + if (s < 0) { + perror("Unable to create socket"); + exit(EXIT_FAILURE); + } + int optval = 1; + if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(int)) < 0) + printf("Cannot set SO_REUSEADDR option on listen socket (%s)\n", strerror(errno)); - if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(int)) < 0) - printf("Cannot set SO_REUSEADDR option on listen socket (%s)\n", strerror(errno)); + if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(int)) < 0) + printf("Cannot set SO_REUSEADDR option on listen socket (%s)\n", strerror(errno)); - if (bind(s, (struct sockaddr*)&addr, sizeof(addr)) < 0) { - perror("Unable to bind"); - exit(EXIT_FAILURE); - } - if (listen(s, 1) < 0) { - perror("Unable to listen"); - exit(EXIT_FAILURE); - } + if (bind(s, (struct sockaddr*)&addr, sizeof(addr)) < 0) { + perror("Unable to bind"); + exit(EXIT_FAILURE); + } + if (listen(s, 1) < 0) { + perror("Unable to listen"); + exit(EXIT_FAILURE); + } - return s; + return s; } void setNonBlock(int fd) { @@ -54,30 +54,30 @@ void setNonBlock(int fd) { void init_openssl() { - SSL_load_error_strings(); - OpenSSL_add_ssl_algorithms(); + SSL_load_error_strings(); + OpenSSL_add_ssl_algorithms(); } void cleanup_openssl() { - EVP_cleanup(); + EVP_cleanup(); } SSL_CTX *create_context() { - const SSL_METHOD *method; - SSL_CTX *ctx; + const SSL_METHOD *method; + SSL_CTX *ctx; - method = SSLv23_server_method(); + method = SSLv23_server_method(); - ctx = SSL_CTX_new(method); - if (!ctx) { - perror("Unable to create SSL context"); - ERR_print_errors_fp(stderr); - exit(EXIT_FAILURE); - } + ctx = SSL_CTX_new(method); + if (!ctx) { + perror("Unable to create SSL context"); + ERR_print_errors_fp(stderr); + exit(EXIT_FAILURE); + } - return ctx; + return ctx; } //#define CERTIFICATE_FILE "cert.pem" @@ -87,66 +87,66 @@ SSL_CTX *create_context() std::pair createCerts(pem_password_cb* password) { /* - auto bio = BIO_new_file("cert.pem", "r"); - if(!bio) { - ERR_print_errors_fp(stderr); - exit(EXIT_FAILURE); - } + auto bio = BIO_new_file("cert.pem", "r"); + if(!bio) { + ERR_print_errors_fp(stderr); + exit(EXIT_FAILURE); + } - auto cert = PEM_read_bio_X509(bio, nullptr, password, nullptr); - if(!cert) { - ERR_print_errors_fp(stderr); - exit(EXIT_FAILURE); - } - BIO_free(bio); + auto cert = PEM_read_bio_X509(bio, nullptr, password, nullptr); + if(!cert) { + ERR_print_errors_fp(stderr); + exit(EXIT_FAILURE); + } + BIO_free(bio); - bio = BIO_new_file("key.pem", "r"); - if(!bio) { - ERR_print_errors_fp(stderr); - exit(EXIT_FAILURE); - } - auto key = PEM_read_bio_PrivateKey(bio, nullptr, password, nullptr); + bio = BIO_new_file("key.pem", "r"); + if(!bio) { + ERR_print_errors_fp(stderr); + exit(EXIT_FAILURE); + } + auto key = PEM_read_bio_PrivateKey(bio, nullptr, password, nullptr); - if(!key) { - ERR_print_errors_fp(stderr); - exit(EXIT_FAILURE); - } - BIO_free(bio); + if(!key) { + ERR_print_errors_fp(stderr); + exit(EXIT_FAILURE); + } + BIO_free(bio); */ - auto key = std::unique_ptr(EVP_PKEY_new(), ::EVP_PKEY_free); + auto key = std::unique_ptr(EVP_PKEY_new(), ::EVP_PKEY_free); - auto rsa = RSA_new(); - auto e = std::unique_ptr(BN_new(), ::BN_free); - BN_set_word(e.get(), RSA_F4); - if(!RSA_generate_key_ex(rsa, 2048, e.get(), nullptr)) return {nullptr, nullptr}; - EVP_PKEY_assign_RSA(key.get(), rsa); + auto rsa = RSA_new(); + auto e = std::unique_ptr(BN_new(), ::BN_free); + BN_set_word(e.get(), RSA_F4); + if(!RSA_generate_key_ex(rsa, 2048, e.get(), nullptr)) return {nullptr, nullptr}; + EVP_PKEY_assign_RSA(key.get(), rsa); - auto cert = X509_new(); - X509_set_pubkey(cert, key.get()); + auto cert = X509_new(); + X509_set_pubkey(cert, key.get()); - ASN1_INTEGER_set(X509_get_serialNumber(cert), 3); - X509_gmtime_adj(X509_get_notBefore(cert), 0); - X509_gmtime_adj(X509_get_notAfter(cert), 31536000L); + ASN1_INTEGER_set(X509_get_serialNumber(cert), 3); + X509_gmtime_adj(X509_get_notBefore(cert), 0); + X509_gmtime_adj(X509_get_notAfter(cert), 31536000L); - X509_NAME* name = X509_get_subject_name(cert); - X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (unsigned char *) "DE", -1, -1, 0); - X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, (unsigned char *) "TeaSpeak", -1, -1, 0); - X509_NAME_add_entry_by_txt(name, "OU", MBSTRING_ASC, (unsigned char *) "Web Server", -1, -1, 0); - X509_NAME_add_entry_by_txt(name, "emailAddress", MBSTRING_ASC, (unsigned char *)"contact@teaspeak.de", -1, -1, 0); - X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (unsigned char *)"web.teaspeak.de", -1, -1, 0); + X509_NAME* name = X509_get_subject_name(cert); + X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (unsigned char *) "DE", -1, -1, 0); + X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, (unsigned char *) "TeaSpeak", -1, -1, 0); + X509_NAME_add_entry_by_txt(name, "OU", MBSTRING_ASC, (unsigned char *) "Web Server", -1, -1, 0); + X509_NAME_add_entry_by_txt(name, "emailAddress", MBSTRING_ASC, (unsigned char *)"contact@teaspeak.de", -1, -1, 0); + X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (unsigned char *)"web.teaspeak.de", -1, -1, 0); - X509_set_issuer_name(cert, name); - X509_set_subject_name(cert, name); + X509_set_issuer_name(cert, name); + X509_set_subject_name(cert, name); - X509_sign(cert, key.get(), EVP_sha512()); + X509_sign(cert, key.get(), EVP_sha512()); - return {key.release(), cert}; + return {key.release(), cert}; }; /* @@ -173,131 +173,131 @@ EOF void configure_context(SSL_CTX *ctx) { - SSL_CTX_set_ecdh_auto(ctx, 1); - auto certs = createCerts([](char* buffer, int length, int rwflag, void* data) -> int { - std::string password = "markus"; - memcpy(buffer, password.data(), password.length()); - return password.length(); - }); + SSL_CTX_set_ecdh_auto(ctx, 1); + auto certs = createCerts([](char* buffer, int length, int rwflag, void* data) -> int { + std::string password = "markus"; + memcpy(buffer, password.data(), password.length()); + return password.length(); + }); - PEM_write_X509(stdout, certs.second); + PEM_write_X509(stdout, certs.second); - if (SSL_CTX_use_PrivateKey(ctx, certs.first) <= 0 ) { - ERR_print_errors_fp(stderr); - exit(EXIT_FAILURE); - } + if (SSL_CTX_use_PrivateKey(ctx, certs.first) <= 0 ) { + ERR_print_errors_fp(stderr); + exit(EXIT_FAILURE); + } - if (SSL_CTX_use_certificate(ctx, certs.second) <= 0 ) { - ERR_print_errors_fp(stderr); - exit(EXIT_FAILURE); - } + if (SSL_CTX_use_certificate(ctx, certs.second) <= 0 ) { + ERR_print_errors_fp(stderr); + exit(EXIT_FAILURE); + } } struct Client { - int fd; - ssl::SSLSocket ssl; - ws::WebSocket ws; + int fd; + ssl::SSLSocket ssl; + ws::WebSocket ws; - std::deque writeQueue; + std::deque writeQueue; - event* read; - event* write; + event* read; + event* write; }; void handleRead(int fd, short, void* ptrClient) { - auto client = (Client*) ptrClient; + auto client = (Client*) ptrClient; - ssize_t bufferLength = 1024; - char buffer[bufferLength]; + ssize_t bufferLength = 1024; + char buffer[bufferLength]; - bufferLength = recv(client->fd, buffer, bufferLength, MSG_DONTWAIT); - if(bufferLength < 0){ - cout << "Invalid read: " << bufferLength << " / " << errno << endl; - event_del(client->read); - event_del(client->write); - return; - } else if(bufferLength == 0) return; + bufferLength = recv(client->fd, buffer, bufferLength, MSG_DONTWAIT); + if(bufferLength < 0){ + cout << "Invalid read: " << bufferLength << " / " << errno << endl; + event_del(client->read); + event_del(client->write); + return; + } else if(bufferLength == 0) return; - cout << "Read " << bufferLength << " bytes" << endl; - client->ssl.proceedMessage(string(buffer, bufferLength)); + cout << "Read " << bufferLength << " bytes" << endl; + client->ssl.proceedMessage(string(buffer, bufferLength)); } void handleWrite(int fd, short, void* ptrClient) { - auto client = (Client*) ptrClient; - while(!client->writeQueue.empty()) { - auto message = std::move(client->writeQueue.front()); - client->writeQueue.pop_front(); - send(client->fd, message.data(), message.length(), 0); - cout << "Send " << message.length() << " bytes" << endl; - } + auto client = (Client*) ptrClient; + while(!client->writeQueue.empty()) { + auto message = std::move(client->writeQueue.front()); + client->writeQueue.pop_front(); + send(client->fd, message.data(), message.length(), 0); + cout << "Send " << message.length() << " bytes" << endl; + } } int main(int argc, char **argv) { - int sock; - SSL_CTX *ctx; + int sock; + SSL_CTX *ctx; - init_openssl(); - ctx = create_context(); - configure_context(ctx); + init_openssl(); + ctx = create_context(); + configure_context(ctx); - sock = create_socket(4433); + sock = create_socket(4433); - auto evLoop = event_base_new(); - threads::Thread([evLoop](){ - while(true) { - event_base_dispatch(evLoop); - threads::self::sleep_for(std::chrono::milliseconds(10)); - }; - cerr << "event_base_dispatch() exited!" << endl; - }).detach(); - /* Handle connections */ - cout << "Waiting!" << endl; - while(1) { - struct sockaddr_in addr{}; - uint len = sizeof(addr); + auto evLoop = event_base_new(); + threads::Thread([evLoop](){ + while(true) { + event_base_dispatch(evLoop); + threads::self::sleep_for(std::chrono::milliseconds(10)); + }; + cerr << "event_base_dispatch() exited!" << endl; + }).detach(); + /* Handle connections */ + cout << "Waiting!" << endl; + while(1) { + struct sockaddr_in addr{}; + uint len = sizeof(addr); - int fd = accept(sock, (struct sockaddr*)&addr, &len); - if (fd < 0) { - perror("Unable to accept"); - exit(EXIT_FAILURE); - } - auto client = new Client{}; - client->fd = fd; + int fd = accept(sock, (struct sockaddr*)&addr, &len); + if (fd < 0) { + perror("Unable to accept"); + exit(EXIT_FAILURE); + } + auto client = new Client{}; + client->fd = fd; - client->read = event_new(evLoop, fd, EV_READ | EV_PERSIST, handleRead, client); - client->write = event_new(evLoop, fd, EV_WRITE, handleWrite, client); + client->read = event_new(evLoop, fd, EV_READ | EV_PERSIST, handleRead, client); + client->write = event_new(evLoop, fd, EV_WRITE, handleWrite, client); - client->ssl.callback_error = [](ssl::SSLSocketError, const std::string& error) { - cout << error << endl; - }; - client->ssl.callback_write = [client](const std::string& buffer) { - client->writeQueue.push_back(buffer); - event_add(client->write, nullptr); - }; - client->ssl.callback_read = [client](const std::string& buffer) { - cout << buffer; - client->ws.proceedMessage(buffer); - }; - auto ptr = std::shared_ptr(ctx, [](SSL_CTX*){}); - client->ssl.initialize(ptr); + client->ssl.callback_error = [](ssl::SSLSocketError, const std::string& error) { + cout << error << endl; + }; + client->ssl.callback_write = [client](const std::string& buffer) { + client->writeQueue.push_back(buffer); + event_add(client->write, nullptr); + }; + client->ssl.callback_read = [client](const std::string& buffer) { + cout << buffer; + client->ws.proceedMessage(buffer); + }; + auto ptr = std::shared_ptr(ctx, [](SSL_CTX*){}); + client->ssl.initialize(ptr); - client->ws.on_message = [](const std::string& message) { - cout << "[WS] Message: " << endl << message << endl; - }; - client->ws.write_message = [client](const std::string& data) { - cout << "[WS] Send: " << endl << data << endl; - client->ssl.sendMessage(data); - }; + client->ws.on_message = [](const std::string& message) { + cout << "[WS] Message: " << endl << message << endl; + }; + client->ws.write_message = [client](const std::string& data) { + cout << "[WS] Send: " << endl << data << endl; + client->ssl.sendMessage(data); + }; - client->ws.initialize(); + client->ws.initialize(); - event_add(client->read, nullptr); - } + event_add(client->read, nullptr); + } - close(sock); - SSL_CTX_free(ctx); - cleanup_openssl(); + close(sock); + SSL_CTX_free(ctx); + cleanup_openssl(); } \ No newline at end of file