diff --git a/.gitignore b/.gitignore index 117f8bc..4eef7e1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,5 @@ build -lib out .cache -./libs -libs/ buildpc buildhost \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 3aab874..7132f62 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,10 +43,14 @@ message("PROJECT_NAME: ${PROJECT_NAME}") file( GLOB_RECURSE APP_SRC # - src/*.cpp # - src/*.c # - src/*.hpp # - src/*.h # + appsrc/*.cpp # + appsrc/*.c # + appsrc/*.hpp # + appsrc/*.h # + appdep/*.cpp # + appdep/*.c # + appdep/*.hpp # + appdep/*.h # app_protocols/*.cpp # app_protocols/*.c # app_protocols/*.hpp # @@ -70,18 +74,25 @@ zadd_executable( # INCLUDE_DIRECTORIES # INCLUDE_DIRECTORIES - src/ - src/iflytop/core/spdlog/include + appdep/iflytop/core/spdlog/include + appsrc/ + appdep/ app_protocols/ ./ + + appdep/libs/libixwebsocket/include + # # LINK_LIBRARIES # LINK_LIBRARIES pthread + ixwebsocket + # # LINK_DIRECTORIES # LINK_DIRECTORIES # + appdep/libs/libixwebsocket/lib/ ) diff --git a/src/components/simple_udp/simple_udp.cpp b/appdep/components/simple_udp/simple_udp.cpp similarity index 100% rename from src/components/simple_udp/simple_udp.cpp rename to appdep/components/simple_udp/simple_udp.cpp diff --git a/src/components/simple_udp/simple_udp.hpp b/appdep/components/simple_udp/simple_udp.hpp similarity index 100% rename from src/components/simple_udp/simple_udp.hpp rename to appdep/components/simple_udp/simple_udp.hpp diff --git a/src/components/sqlite_orm/README.md b/appdep/components/sqlite_orm/README.md similarity index 100% rename from src/components/sqlite_orm/README.md rename to appdep/components/sqlite_orm/README.md diff --git a/src/components/sqlite_orm/sqlite_orm.hpp b/appdep/components/sqlite_orm/sqlite_orm.hpp similarity index 100% rename from src/components/sqlite_orm/sqlite_orm.hpp rename to appdep/components/sqlite_orm/sqlite_orm.hpp diff --git a/src/components/uart_printer/uart_printer.cpp b/appdep/components/uart_printer/uart_printer.cpp similarity index 100% rename from src/components/uart_printer/uart_printer.cpp rename to appdep/components/uart_printer/uart_printer.cpp diff --git a/src/components/uart_printer/uart_printer.hpp b/appdep/components/uart_printer/uart_printer.hpp similarity index 100% rename from src/components/uart_printer/uart_printer.hpp rename to appdep/components/uart_printer/uart_printer.hpp diff --git a/src/components/ziconv.cpp b/appdep/components/ziconv.cpp similarity index 100% rename from src/components/ziconv.cpp rename to appdep/components/ziconv.cpp diff --git a/src/components/ziconv.hpp b/appdep/components/ziconv.hpp similarity index 100% rename from src/components/ziconv.hpp rename to appdep/components/ziconv.hpp diff --git a/appdep/components/zservice_container/zservice_container.cpp b/appdep/components/zservice_container/zservice_container.cpp new file mode 100644 index 0000000..4f93ceb --- /dev/null +++ b/appdep/components/zservice_container/zservice_container.cpp @@ -0,0 +1,8 @@ +#include "zservice_container.hpp" +using namespace iflytop; +using namespace std; + +ServiceContrainer& ServiceContrainer::get() { + static ServiceContrainer serviceContrainer; + return serviceContrainer; +} \ No newline at end of file diff --git a/appdep/components/zservice_container/zservice_container.hpp b/appdep/components/zservice_container/zservice_container.hpp new file mode 100644 index 0000000..6846ea3 --- /dev/null +++ b/appdep/components/zservice_container/zservice_container.hpp @@ -0,0 +1,204 @@ +// +// Created by zwsd +// + +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * @brief + * + * service: ServiceContrainer + * + * 监听事件: + * 依赖状态: + * 依赖服务: + * 作用: + * + */ +// std::shared_ptr buf(new Buffer()); +// ZserviceContainerAny any(buf); +// std::shared_ptr b = any.Get>(); +// assert(buf.get() == b.get()); +namespace iflytop { +using namespace std; + +class ZserviceContainerAny { + public: + ZserviceContainerAny() : content_(nullptr) {} + ~ZserviceContainerAny() { delete content_; } + + template + explicit ZserviceContainerAny(const ValueType& value) : content_(new Holder(value)) {} + + ZserviceContainerAny(const ZserviceContainerAny& other) + : content_(other.content_ ? other.content_->clone() : nullptr) {} + + public: + ZserviceContainerAny& swap(ZserviceContainerAny& rhs) { + std::swap(content_, rhs.content_); + return *this; + } + + template + ZserviceContainerAny& operator=(const ValueType& rhs) { + ZserviceContainerAny(rhs).swap(*this); + return *this; + } + + ZserviceContainerAny& operator=(const ZserviceContainerAny& rhs) { + ZserviceContainerAny(rhs).swap(*this); + return *this; + } + + bool IsEmpty() const { return !content_; } + + const std::type_info& GetType() const { return content_ ? content_->GetType() : typeid(void); } + + template + ValueType operator()() const { + return Get(); + } + + template + ValueType Get() const { + if (GetType() == typeid(ValueType)) { + return static_cast*>(content_)->held_; + } else { + return ValueType(); + } + } + + protected: + class ZPlaceHolder { + public: + virtual ~ZPlaceHolder() {} + + public: + virtual const std::type_info& GetType() const = 0; + virtual ZPlaceHolder* clone() const = 0; + }; + + template + class Holder : public ZPlaceHolder { + public: + Holder(const ValueType& value) : held_(value) {} + + virtual const std::type_info& GetType() const { return typeid(ValueType); } + + virtual ZPlaceHolder* clone() const { return new Holder(held_); } + + ValueType held_; + }; + + protected: + ZPlaceHolder* content_; + template + friend ValueType* zany_cast(ZserviceContainerAny*); +}; + +template +ValueType* zany_cast(ZserviceContainerAny* any) { + if (any && any->GetType() == typeid(ValueType)) { + return &(static_cast*>(any->content_)->held_); + } + + return nullptr; +} + +template +const ValueType* zany_cast(const ZserviceContainerAny* any) { + return zany_cast(const_cast(any)); +} + +template +ValueType zany_cast(const ZserviceContainerAny& any) { + const ValueType* result = zany_cast(&any); + assert(result); + + if (!result) { + return ValueType(); + } + + return *result; +} + +class ServiceContrainer { + map services; + ServiceContrainer(){}; + + public: + static ServiceContrainer& get(); + + template + void regAndInitializeService(shared_ptr object) { + if (object == nullptr) { + return; + } + object->initialize(); + type_index index = typeid(T); + services[index] = ZserviceContainerAny(object); + }; + template + void regService(shared_ptr object) { + if (object == nullptr) { + return; + } + type_index index = typeid(T); + services[index] = ZserviceContainerAny(object); + }; + template + shared_ptr getService() { + type_index index = typeid(T); + auto result = services.find(index); + if (result == services.end()) { + return nullptr; + } + return result->second.Get>(); + }; + + template + void getToService(shared_ptr& service) { + type_index index = typeid(T); + auto result = services.find(index); + if (result == services.end()) { + service = nullptr; + } + service = result->second.Get>(); + }; +}; + +#define GET_SERVICE(type) (ServiceContrainer::get().getService()) +#define GET_TO_SERVICE(value) \ + ServiceContrainer::get().getToService(value); \ + if (value == nullptr) { \ + logger->error("[{}:{}]GET_TO_SERVICE({}) fail", __FILE__, __LINE__, #value); \ + exit(-1); \ + }; + +#define BUILD_AND_REG_SERRVICE(type, ...) \ + logger->info("build {}.....", #type); \ + shared_ptr type##_val(new type(__VA_ARGS__)); \ + ServiceContrainer::get().regService(type##_val); + +#define REG_SERRVICE(type,object) \ + shared_ptr type##_val(object); \ + ServiceContrainer::get().regService(type##_val); + +#define BUILD_AND_REG_MOCK_SERRVICE(type, mocktype, ...) \ + logger->info("build {}.....", #type); \ + shared_ptr type##_val(new mocktype(__VA_ARGS__)); \ + ServiceContrainer::get().regService(type##_val); + +} // namespace iflytop \ No newline at end of file diff --git a/src/iflytop/core/basic/any.cpp b/appdep/iflytop/core/basic/any.cpp similarity index 100% rename from src/iflytop/core/basic/any.cpp rename to appdep/iflytop/core/basic/any.cpp diff --git a/src/iflytop/core/basic/any.hpp b/appdep/iflytop/core/basic/any.hpp similarity index 100% rename from src/iflytop/core/basic/any.hpp rename to appdep/iflytop/core/basic/any.hpp diff --git a/src/iflytop/core/basic/autodo.hpp b/appdep/iflytop/core/basic/autodo.hpp similarity index 100% rename from src/iflytop/core/basic/autodo.hpp rename to appdep/iflytop/core/basic/autodo.hpp diff --git a/src/iflytop/core/basic/concurrentqueue/blockingconcurrentqueue.h b/appdep/iflytop/core/basic/concurrentqueue/blockingconcurrentqueue.h similarity index 100% rename from src/iflytop/core/basic/concurrentqueue/blockingconcurrentqueue.h rename to appdep/iflytop/core/basic/concurrentqueue/blockingconcurrentqueue.h diff --git a/src/iflytop/core/basic/concurrentqueue/concurrentqueue.h b/appdep/iflytop/core/basic/concurrentqueue/concurrentqueue.h similarity index 100% rename from src/iflytop/core/basic/concurrentqueue/concurrentqueue.h rename to appdep/iflytop/core/basic/concurrentqueue/concurrentqueue.h diff --git a/src/iflytop/core/basic/ds/binary.hpp b/appdep/iflytop/core/basic/ds/binary.hpp similarity index 100% rename from src/iflytop/core/basic/ds/binary.hpp rename to appdep/iflytop/core/basic/ds/binary.hpp diff --git a/src/iflytop/core/basic/enum_converter.hpp b/appdep/iflytop/core/basic/enum_converter.hpp similarity index 100% rename from src/iflytop/core/basic/enum_converter.hpp rename to appdep/iflytop/core/basic/enum_converter.hpp diff --git a/src/iflytop/core/basic/marco/basic.h b/appdep/iflytop/core/basic/marco/basic.h similarity index 100% rename from src/iflytop/core/basic/marco/basic.h rename to appdep/iflytop/core/basic/marco/basic.h diff --git a/src/iflytop/core/basic/marco/data.hpp b/appdep/iflytop/core/basic/marco/data.hpp similarity index 100% rename from src/iflytop/core/basic/marco/data.hpp rename to appdep/iflytop/core/basic/marco/data.hpp diff --git a/src/iflytop/core/basic/marco/marco.hpp b/appdep/iflytop/core/basic/marco/marco.hpp similarity index 100% rename from src/iflytop/core/basic/marco/marco.hpp rename to appdep/iflytop/core/basic/marco/marco.hpp diff --git a/src/iflytop/core/basic/marco/marco_list.h b/appdep/iflytop/core/basic/marco/marco_list.h similarity index 100% rename from src/iflytop/core/basic/marco/marco_list.h rename to appdep/iflytop/core/basic/marco/marco_list.h diff --git a/src/iflytop/core/basic/nlohmann/README.md b/appdep/iflytop/core/basic/nlohmann/README.md similarity index 100% rename from src/iflytop/core/basic/nlohmann/README.md rename to appdep/iflytop/core/basic/nlohmann/README.md diff --git a/src/iflytop/core/basic/nlohmann/json.hpp b/appdep/iflytop/core/basic/nlohmann/json.hpp similarity index 100% rename from src/iflytop/core/basic/nlohmann/json.hpp rename to appdep/iflytop/core/basic/nlohmann/json.hpp diff --git a/src/iflytop/core/basic/nod/nod.hpp b/appdep/iflytop/core/basic/nod/nod.hpp similarity index 100% rename from src/iflytop/core/basic/nod/nod.hpp rename to appdep/iflytop/core/basic/nod/nod.hpp diff --git a/src/iflytop/core/basic/signal/signal.cpp b/appdep/iflytop/core/basic/signal/signal.cpp similarity index 100% rename from src/iflytop/core/basic/signal/signal.cpp rename to appdep/iflytop/core/basic/signal/signal.cpp diff --git a/src/iflytop/core/basic/signal/signal.hpp b/appdep/iflytop/core/basic/signal/signal.hpp similarity index 100% rename from src/iflytop/core/basic/signal/signal.hpp rename to appdep/iflytop/core/basic/signal/signal.hpp diff --git a/src/iflytop/core/basic/zbin.hpp b/appdep/iflytop/core/basic/zbin.hpp similarity index 100% rename from src/iflytop/core/basic/zbin.hpp rename to appdep/iflytop/core/basic/zbin.hpp diff --git a/src/iflytop/core/components/audio/wav_recorder.cpp b/appdep/iflytop/core/components/audio/wav_recorder.cpp similarity index 100% rename from src/iflytop/core/components/audio/wav_recorder.cpp rename to appdep/iflytop/core/components/audio/wav_recorder.cpp diff --git a/src/iflytop/core/components/audio/wav_recorder.hpp b/appdep/iflytop/core/components/audio/wav_recorder.hpp similarity index 100% rename from src/iflytop/core/components/audio/wav_recorder.hpp rename to appdep/iflytop/core/components/audio/wav_recorder.hpp diff --git a/src/iflytop/core/components/audio/wavheader.hpp b/appdep/iflytop/core/components/audio/wavheader.hpp similarity index 100% rename from src/iflytop/core/components/audio/wavheader.hpp rename to appdep/iflytop/core/components/audio/wavheader.hpp diff --git a/src/iflytop/core/components/config_template/config_template.hpp b/appdep/iflytop/core/components/config_template/config_template.hpp similarity index 100% rename from src/iflytop/core/components/config_template/config_template.hpp rename to appdep/iflytop/core/components/config_template/config_template.hpp diff --git a/src/iflytop/core/components/fileutils.cpp b/appdep/iflytop/core/components/fileutils.cpp similarity index 100% rename from src/iflytop/core/components/fileutils.cpp rename to appdep/iflytop/core/components/fileutils.cpp diff --git a/src/iflytop/core/components/fileutils.hpp b/appdep/iflytop/core/components/fileutils.hpp similarity index 100% rename from src/iflytop/core/components/fileutils.hpp rename to appdep/iflytop/core/components/fileutils.hpp diff --git a/src/iflytop/core/components/jobs/thread_pool_task_scheduler.cpp b/appdep/iflytop/core/components/jobs/thread_pool_task_scheduler.cpp similarity index 100% rename from src/iflytop/core/components/jobs/thread_pool_task_scheduler.cpp rename to appdep/iflytop/core/components/jobs/thread_pool_task_scheduler.cpp diff --git a/src/iflytop/core/components/jobs/thread_pool_task_scheduler.hpp b/appdep/iflytop/core/components/jobs/thread_pool_task_scheduler.hpp similarity index 100% rename from src/iflytop/core/components/jobs/thread_pool_task_scheduler.hpp rename to appdep/iflytop/core/components/jobs/thread_pool_task_scheduler.hpp diff --git a/src/iflytop/core/components/jobs/work_queue.cpp b/appdep/iflytop/core/components/jobs/work_queue.cpp similarity index 100% rename from src/iflytop/core/components/jobs/work_queue.cpp rename to appdep/iflytop/core/components/jobs/work_queue.cpp diff --git a/src/iflytop/core/components/jobs/work_queue.hpp b/appdep/iflytop/core/components/jobs/work_queue.hpp similarity index 100% rename from src/iflytop/core/components/jobs/work_queue.hpp rename to appdep/iflytop/core/components/jobs/work_queue.hpp diff --git a/src/iflytop/core/components/modbus/modbus.cpp b/appdep/iflytop/core/components/modbus/modbus.cpp similarity index 100% rename from src/iflytop/core/components/modbus/modbus.cpp rename to appdep/iflytop/core/components/modbus/modbus.cpp diff --git a/src/iflytop/core/components/modbus/modbus.hpp b/appdep/iflytop/core/components/modbus/modbus.hpp similarity index 100% rename from src/iflytop/core/components/modbus/modbus.hpp rename to appdep/iflytop/core/components/modbus/modbus.hpp diff --git a/src/iflytop/core/components/modbus/zmodbus_common.c b/appdep/iflytop/core/components/modbus/zmodbus_common.c similarity index 100% rename from src/iflytop/core/components/modbus/zmodbus_common.c rename to appdep/iflytop/core/components/modbus/zmodbus_common.c diff --git a/src/iflytop/core/components/modbus/zmodbus_common.h b/appdep/iflytop/core/components/modbus/zmodbus_common.h similarity index 100% rename from src/iflytop/core/components/modbus/zmodbus_common.h rename to appdep/iflytop/core/components/modbus/zmodbus_common.h diff --git a/src/iflytop/core/components/modbus/zmodbus_master.c b/appdep/iflytop/core/components/modbus/zmodbus_master.c similarity index 100% rename from src/iflytop/core/components/modbus/zmodbus_master.c rename to appdep/iflytop/core/components/modbus/zmodbus_master.c diff --git a/src/iflytop/core/components/modbus/zmodbus_master.h b/appdep/iflytop/core/components/modbus/zmodbus_master.h similarity index 100% rename from src/iflytop/core/components/modbus/zmodbus_master.h rename to appdep/iflytop/core/components/modbus/zmodbus_master.h diff --git a/src/iflytop/core/components/modbus/zmodbus_slave.c b/appdep/iflytop/core/components/modbus/zmodbus_slave.c similarity index 100% rename from src/iflytop/core/components/modbus/zmodbus_slave.c rename to appdep/iflytop/core/components/modbus/zmodbus_slave.c diff --git a/src/iflytop/core/components/modbus/zmodbus_slave.h b/appdep/iflytop/core/components/modbus/zmodbus_slave.h similarity index 100% rename from src/iflytop/core/components/modbus/zmodbus_slave.h rename to appdep/iflytop/core/components/modbus/zmodbus_slave.h diff --git a/src/iflytop/core/components/process/.clang-format b/appdep/iflytop/core/components/process/.clang-format similarity index 100% rename from src/iflytop/core/components/process/.clang-format rename to appdep/iflytop/core/components/process/.clang-format diff --git a/src/iflytop/core/components/process/README.md b/appdep/iflytop/core/components/process/README.md similarity index 100% rename from src/iflytop/core/components/process/README.md rename to appdep/iflytop/core/components/process/README.md diff --git a/src/iflytop/core/components/process/process.cpp b/appdep/iflytop/core/components/process/process.cpp similarity index 100% rename from src/iflytop/core/components/process/process.cpp rename to appdep/iflytop/core/components/process/process.cpp diff --git a/src/iflytop/core/components/process/process.hpp b/appdep/iflytop/core/components/process/process.hpp similarity index 100% rename from src/iflytop/core/components/process/process.hpp rename to appdep/iflytop/core/components/process/process.hpp diff --git a/src/iflytop/core/components/process/process_unix.cpp b/appdep/iflytop/core/components/process/process_unix.cpp similarity index 100% rename from src/iflytop/core/components/process/process_unix.cpp rename to appdep/iflytop/core/components/process/process_unix.cpp diff --git a/src/iflytop/core/components/sha256/IFLYTOP_README.md b/appdep/iflytop/core/components/sha256/IFLYTOP_README.md similarity index 100% rename from src/iflytop/core/components/sha256/IFLYTOP_README.md rename to appdep/iflytop/core/components/sha256/IFLYTOP_README.md diff --git a/src/iflytop/core/components/sha256/README.md b/appdep/iflytop/core/components/sha256/README.md similarity index 100% rename from src/iflytop/core/components/sha256/README.md rename to appdep/iflytop/core/components/sha256/README.md diff --git a/src/iflytop/core/components/sha256/sha256.hpp b/appdep/iflytop/core/components/sha256/sha256.hpp similarity index 100% rename from src/iflytop/core/components/sha256/sha256.hpp rename to appdep/iflytop/core/components/sha256/sha256.hpp diff --git a/src/iflytop/core/components/stringutils.cpp b/appdep/iflytop/core/components/stringutils.cpp similarity index 100% rename from src/iflytop/core/components/stringutils.cpp rename to appdep/iflytop/core/components/stringutils.cpp diff --git a/src/iflytop/core/components/stringutils.hpp b/appdep/iflytop/core/components/stringutils.hpp similarity index 100% rename from src/iflytop/core/components/stringutils.hpp rename to appdep/iflytop/core/components/stringutils.hpp diff --git a/src/iflytop/core/components/timer/simple_timer.cpp b/appdep/iflytop/core/components/timer/simple_timer.cpp similarity index 100% rename from src/iflytop/core/components/timer/simple_timer.cpp rename to appdep/iflytop/core/components/timer/simple_timer.cpp diff --git a/src/iflytop/core/components/timer/simple_timer.hpp b/appdep/iflytop/core/components/timer/simple_timer.hpp similarity index 100% rename from src/iflytop/core/components/timer/simple_timer.hpp rename to appdep/iflytop/core/components/timer/simple_timer.hpp diff --git a/src/iflytop/core/components/timeutils.hpp b/appdep/iflytop/core/components/timeutils.hpp similarity index 100% rename from src/iflytop/core/components/timeutils.hpp rename to appdep/iflytop/core/components/timeutils.hpp diff --git a/src/iflytop/core/components/uart/uart.cpp b/appdep/iflytop/core/components/uart/uart.cpp similarity index 100% rename from src/iflytop/core/components/uart/uart.cpp rename to appdep/iflytop/core/components/uart/uart.cpp diff --git a/src/iflytop/core/components/uart/uart.hpp b/appdep/iflytop/core/components/uart/uart.hpp similarity index 100% rename from src/iflytop/core/components/uart/uart.hpp rename to appdep/iflytop/core/components/uart/uart.hpp diff --git a/src/iflytop/core/core.hpp b/appdep/iflytop/core/core.hpp similarity index 100% rename from src/iflytop/core/core.hpp rename to appdep/iflytop/core/core.hpp diff --git a/src/iflytop/core/error/error_code.cpp b/appdep/iflytop/core/error/error_code.cpp similarity index 100% rename from src/iflytop/core/error/error_code.cpp rename to appdep/iflytop/core/error/error_code.cpp diff --git a/src/iflytop/core/error/error_code.hpp b/appdep/iflytop/core/error/error_code.hpp similarity index 100% rename from src/iflytop/core/error/error_code.hpp rename to appdep/iflytop/core/error/error_code.hpp diff --git a/src/iflytop/core/linuxcoreutils/linuxcoreutils.cpp b/appdep/iflytop/core/linuxcoreutils/linuxcoreutils.cpp similarity index 100% rename from src/iflytop/core/linuxcoreutils/linuxcoreutils.cpp rename to appdep/iflytop/core/linuxcoreutils/linuxcoreutils.cpp diff --git a/src/iflytop/core/linuxcoreutils/linuxcoreutils.hpp b/appdep/iflytop/core/linuxcoreutils/linuxcoreutils.hpp similarity index 100% rename from src/iflytop/core/linuxcoreutils/linuxcoreutils.hpp rename to appdep/iflytop/core/linuxcoreutils/linuxcoreutils.hpp diff --git a/src/iflytop/core/spdlog/README.md b/appdep/iflytop/core/spdlog/README.md similarity index 100% rename from src/iflytop/core/spdlog/README.md rename to appdep/iflytop/core/spdlog/README.md diff --git a/src/iflytop/core/spdlog/include/spdlog/async.h b/appdep/iflytop/core/spdlog/include/spdlog/async.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/async.h rename to appdep/iflytop/core/spdlog/include/spdlog/async.h diff --git a/src/iflytop/core/spdlog/include/spdlog/async_logger-inl.h b/appdep/iflytop/core/spdlog/include/spdlog/async_logger-inl.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/async_logger-inl.h rename to appdep/iflytop/core/spdlog/include/spdlog/async_logger-inl.h diff --git a/src/iflytop/core/spdlog/include/spdlog/async_logger.h b/appdep/iflytop/core/spdlog/include/spdlog/async_logger.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/async_logger.h rename to appdep/iflytop/core/spdlog/include/spdlog/async_logger.h diff --git a/src/iflytop/core/spdlog/include/spdlog/cfg/argv.h b/appdep/iflytop/core/spdlog/include/spdlog/cfg/argv.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/cfg/argv.h rename to appdep/iflytop/core/spdlog/include/spdlog/cfg/argv.h diff --git a/src/iflytop/core/spdlog/include/spdlog/cfg/env.h b/appdep/iflytop/core/spdlog/include/spdlog/cfg/env.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/cfg/env.h rename to appdep/iflytop/core/spdlog/include/spdlog/cfg/env.h diff --git a/src/iflytop/core/spdlog/include/spdlog/cfg/helpers-inl.h b/appdep/iflytop/core/spdlog/include/spdlog/cfg/helpers-inl.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/cfg/helpers-inl.h rename to appdep/iflytop/core/spdlog/include/spdlog/cfg/helpers-inl.h diff --git a/src/iflytop/core/spdlog/include/spdlog/cfg/helpers.h b/appdep/iflytop/core/spdlog/include/spdlog/cfg/helpers.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/cfg/helpers.h rename to appdep/iflytop/core/spdlog/include/spdlog/cfg/helpers.h diff --git a/src/iflytop/core/spdlog/include/spdlog/common-inl.h b/appdep/iflytop/core/spdlog/include/spdlog/common-inl.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/common-inl.h rename to appdep/iflytop/core/spdlog/include/spdlog/common-inl.h diff --git a/src/iflytop/core/spdlog/include/spdlog/common.h b/appdep/iflytop/core/spdlog/include/spdlog/common.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/common.h rename to appdep/iflytop/core/spdlog/include/spdlog/common.h diff --git a/src/iflytop/core/spdlog/include/spdlog/details/backtracer-inl.h b/appdep/iflytop/core/spdlog/include/spdlog/details/backtracer-inl.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/details/backtracer-inl.h rename to appdep/iflytop/core/spdlog/include/spdlog/details/backtracer-inl.h diff --git a/src/iflytop/core/spdlog/include/spdlog/details/backtracer.h b/appdep/iflytop/core/spdlog/include/spdlog/details/backtracer.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/details/backtracer.h rename to appdep/iflytop/core/spdlog/include/spdlog/details/backtracer.h diff --git a/src/iflytop/core/spdlog/include/spdlog/details/circular_q.h b/appdep/iflytop/core/spdlog/include/spdlog/details/circular_q.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/details/circular_q.h rename to appdep/iflytop/core/spdlog/include/spdlog/details/circular_q.h diff --git a/src/iflytop/core/spdlog/include/spdlog/details/console_globals.h b/appdep/iflytop/core/spdlog/include/spdlog/details/console_globals.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/details/console_globals.h rename to appdep/iflytop/core/spdlog/include/spdlog/details/console_globals.h diff --git a/src/iflytop/core/spdlog/include/spdlog/details/file_helper-inl.h b/appdep/iflytop/core/spdlog/include/spdlog/details/file_helper-inl.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/details/file_helper-inl.h rename to appdep/iflytop/core/spdlog/include/spdlog/details/file_helper-inl.h diff --git a/src/iflytop/core/spdlog/include/spdlog/details/file_helper.h b/appdep/iflytop/core/spdlog/include/spdlog/details/file_helper.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/details/file_helper.h rename to appdep/iflytop/core/spdlog/include/spdlog/details/file_helper.h diff --git a/src/iflytop/core/spdlog/include/spdlog/details/fmt_helper.h b/appdep/iflytop/core/spdlog/include/spdlog/details/fmt_helper.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/details/fmt_helper.h rename to appdep/iflytop/core/spdlog/include/spdlog/details/fmt_helper.h diff --git a/src/iflytop/core/spdlog/include/spdlog/details/log_msg-inl.h b/appdep/iflytop/core/spdlog/include/spdlog/details/log_msg-inl.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/details/log_msg-inl.h rename to appdep/iflytop/core/spdlog/include/spdlog/details/log_msg-inl.h diff --git a/src/iflytop/core/spdlog/include/spdlog/details/log_msg.h b/appdep/iflytop/core/spdlog/include/spdlog/details/log_msg.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/details/log_msg.h rename to appdep/iflytop/core/spdlog/include/spdlog/details/log_msg.h diff --git a/src/iflytop/core/spdlog/include/spdlog/details/log_msg_buffer-inl.h b/appdep/iflytop/core/spdlog/include/spdlog/details/log_msg_buffer-inl.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/details/log_msg_buffer-inl.h rename to appdep/iflytop/core/spdlog/include/spdlog/details/log_msg_buffer-inl.h diff --git a/src/iflytop/core/spdlog/include/spdlog/details/log_msg_buffer.h b/appdep/iflytop/core/spdlog/include/spdlog/details/log_msg_buffer.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/details/log_msg_buffer.h rename to appdep/iflytop/core/spdlog/include/spdlog/details/log_msg_buffer.h diff --git a/src/iflytop/core/spdlog/include/spdlog/details/mpmc_blocking_q.h b/appdep/iflytop/core/spdlog/include/spdlog/details/mpmc_blocking_q.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/details/mpmc_blocking_q.h rename to appdep/iflytop/core/spdlog/include/spdlog/details/mpmc_blocking_q.h diff --git a/src/iflytop/core/spdlog/include/spdlog/details/null_mutex.h b/appdep/iflytop/core/spdlog/include/spdlog/details/null_mutex.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/details/null_mutex.h rename to appdep/iflytop/core/spdlog/include/spdlog/details/null_mutex.h diff --git a/src/iflytop/core/spdlog/include/spdlog/details/os-inl.h b/appdep/iflytop/core/spdlog/include/spdlog/details/os-inl.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/details/os-inl.h rename to appdep/iflytop/core/spdlog/include/spdlog/details/os-inl.h diff --git a/src/iflytop/core/spdlog/include/spdlog/details/os.h b/appdep/iflytop/core/spdlog/include/spdlog/details/os.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/details/os.h rename to appdep/iflytop/core/spdlog/include/spdlog/details/os.h diff --git a/src/iflytop/core/spdlog/include/spdlog/details/periodic_worker-inl.h b/appdep/iflytop/core/spdlog/include/spdlog/details/periodic_worker-inl.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/details/periodic_worker-inl.h rename to appdep/iflytop/core/spdlog/include/spdlog/details/periodic_worker-inl.h diff --git a/src/iflytop/core/spdlog/include/spdlog/details/periodic_worker.h b/appdep/iflytop/core/spdlog/include/spdlog/details/periodic_worker.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/details/periodic_worker.h rename to appdep/iflytop/core/spdlog/include/spdlog/details/periodic_worker.h diff --git a/src/iflytop/core/spdlog/include/spdlog/details/registry-inl.h b/appdep/iflytop/core/spdlog/include/spdlog/details/registry-inl.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/details/registry-inl.h rename to appdep/iflytop/core/spdlog/include/spdlog/details/registry-inl.h diff --git a/src/iflytop/core/spdlog/include/spdlog/details/registry.h b/appdep/iflytop/core/spdlog/include/spdlog/details/registry.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/details/registry.h rename to appdep/iflytop/core/spdlog/include/spdlog/details/registry.h diff --git a/src/iflytop/core/spdlog/include/spdlog/details/synchronous_factory.h b/appdep/iflytop/core/spdlog/include/spdlog/details/synchronous_factory.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/details/synchronous_factory.h rename to appdep/iflytop/core/spdlog/include/spdlog/details/synchronous_factory.h diff --git a/src/iflytop/core/spdlog/include/spdlog/details/tcp_client-windows.h b/appdep/iflytop/core/spdlog/include/spdlog/details/tcp_client-windows.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/details/tcp_client-windows.h rename to appdep/iflytop/core/spdlog/include/spdlog/details/tcp_client-windows.h diff --git a/src/iflytop/core/spdlog/include/spdlog/details/tcp_client.h b/appdep/iflytop/core/spdlog/include/spdlog/details/tcp_client.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/details/tcp_client.h rename to appdep/iflytop/core/spdlog/include/spdlog/details/tcp_client.h diff --git a/src/iflytop/core/spdlog/include/spdlog/details/thread_pool-inl.h b/appdep/iflytop/core/spdlog/include/spdlog/details/thread_pool-inl.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/details/thread_pool-inl.h rename to appdep/iflytop/core/spdlog/include/spdlog/details/thread_pool-inl.h diff --git a/src/iflytop/core/spdlog/include/spdlog/details/thread_pool.h b/appdep/iflytop/core/spdlog/include/spdlog/details/thread_pool.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/details/thread_pool.h rename to appdep/iflytop/core/spdlog/include/spdlog/details/thread_pool.h diff --git a/src/iflytop/core/spdlog/include/spdlog/details/udp_client-windows.h b/appdep/iflytop/core/spdlog/include/spdlog/details/udp_client-windows.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/details/udp_client-windows.h rename to appdep/iflytop/core/spdlog/include/spdlog/details/udp_client-windows.h diff --git a/src/iflytop/core/spdlog/include/spdlog/details/udp_client.h b/appdep/iflytop/core/spdlog/include/spdlog/details/udp_client.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/details/udp_client.h rename to appdep/iflytop/core/spdlog/include/spdlog/details/udp_client.h diff --git a/src/iflytop/core/spdlog/include/spdlog/details/windows_include.h b/appdep/iflytop/core/spdlog/include/spdlog/details/windows_include.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/details/windows_include.h rename to appdep/iflytop/core/spdlog/include/spdlog/details/windows_include.h diff --git a/src/iflytop/core/spdlog/include/spdlog/fmt/bin_to_hex.h b/appdep/iflytop/core/spdlog/include/spdlog/fmt/bin_to_hex.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/fmt/bin_to_hex.h rename to appdep/iflytop/core/spdlog/include/spdlog/fmt/bin_to_hex.h diff --git a/src/iflytop/core/spdlog/include/spdlog/fmt/bundled/args.h b/appdep/iflytop/core/spdlog/include/spdlog/fmt/bundled/args.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/fmt/bundled/args.h rename to appdep/iflytop/core/spdlog/include/spdlog/fmt/bundled/args.h diff --git a/src/iflytop/core/spdlog/include/spdlog/fmt/bundled/chrono.h b/appdep/iflytop/core/spdlog/include/spdlog/fmt/bundled/chrono.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/fmt/bundled/chrono.h rename to appdep/iflytop/core/spdlog/include/spdlog/fmt/bundled/chrono.h diff --git a/src/iflytop/core/spdlog/include/spdlog/fmt/bundled/color.h b/appdep/iflytop/core/spdlog/include/spdlog/fmt/bundled/color.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/fmt/bundled/color.h rename to appdep/iflytop/core/spdlog/include/spdlog/fmt/bundled/color.h diff --git a/src/iflytop/core/spdlog/include/spdlog/fmt/bundled/compile.h b/appdep/iflytop/core/spdlog/include/spdlog/fmt/bundled/compile.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/fmt/bundled/compile.h rename to appdep/iflytop/core/spdlog/include/spdlog/fmt/bundled/compile.h diff --git a/src/iflytop/core/spdlog/include/spdlog/fmt/bundled/core.h b/appdep/iflytop/core/spdlog/include/spdlog/fmt/bundled/core.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/fmt/bundled/core.h rename to appdep/iflytop/core/spdlog/include/spdlog/fmt/bundled/core.h diff --git a/src/iflytop/core/spdlog/include/spdlog/fmt/bundled/fmt.license.rst b/appdep/iflytop/core/spdlog/include/spdlog/fmt/bundled/fmt.license.rst similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/fmt/bundled/fmt.license.rst rename to appdep/iflytop/core/spdlog/include/spdlog/fmt/bundled/fmt.license.rst diff --git a/src/iflytop/core/spdlog/include/spdlog/fmt/bundled/format-inl.h b/appdep/iflytop/core/spdlog/include/spdlog/fmt/bundled/format-inl.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/fmt/bundled/format-inl.h rename to appdep/iflytop/core/spdlog/include/spdlog/fmt/bundled/format-inl.h diff --git a/src/iflytop/core/spdlog/include/spdlog/fmt/bundled/format.h b/appdep/iflytop/core/spdlog/include/spdlog/fmt/bundled/format.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/fmt/bundled/format.h rename to appdep/iflytop/core/spdlog/include/spdlog/fmt/bundled/format.h diff --git a/src/iflytop/core/spdlog/include/spdlog/fmt/bundled/locale.h b/appdep/iflytop/core/spdlog/include/spdlog/fmt/bundled/locale.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/fmt/bundled/locale.h rename to appdep/iflytop/core/spdlog/include/spdlog/fmt/bundled/locale.h diff --git a/src/iflytop/core/spdlog/include/spdlog/fmt/bundled/os.h b/appdep/iflytop/core/spdlog/include/spdlog/fmt/bundled/os.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/fmt/bundled/os.h rename to appdep/iflytop/core/spdlog/include/spdlog/fmt/bundled/os.h diff --git a/src/iflytop/core/spdlog/include/spdlog/fmt/bundled/ostream.h b/appdep/iflytop/core/spdlog/include/spdlog/fmt/bundled/ostream.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/fmt/bundled/ostream.h rename to appdep/iflytop/core/spdlog/include/spdlog/fmt/bundled/ostream.h diff --git a/src/iflytop/core/spdlog/include/spdlog/fmt/bundled/printf.h b/appdep/iflytop/core/spdlog/include/spdlog/fmt/bundled/printf.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/fmt/bundled/printf.h rename to appdep/iflytop/core/spdlog/include/spdlog/fmt/bundled/printf.h diff --git a/src/iflytop/core/spdlog/include/spdlog/fmt/bundled/ranges.h b/appdep/iflytop/core/spdlog/include/spdlog/fmt/bundled/ranges.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/fmt/bundled/ranges.h rename to appdep/iflytop/core/spdlog/include/spdlog/fmt/bundled/ranges.h diff --git a/src/iflytop/core/spdlog/include/spdlog/fmt/bundled/xchar.h b/appdep/iflytop/core/spdlog/include/spdlog/fmt/bundled/xchar.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/fmt/bundled/xchar.h rename to appdep/iflytop/core/spdlog/include/spdlog/fmt/bundled/xchar.h diff --git a/src/iflytop/core/spdlog/include/spdlog/fmt/chrono.h b/appdep/iflytop/core/spdlog/include/spdlog/fmt/chrono.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/fmt/chrono.h rename to appdep/iflytop/core/spdlog/include/spdlog/fmt/chrono.h diff --git a/src/iflytop/core/spdlog/include/spdlog/fmt/compile.h b/appdep/iflytop/core/spdlog/include/spdlog/fmt/compile.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/fmt/compile.h rename to appdep/iflytop/core/spdlog/include/spdlog/fmt/compile.h diff --git a/src/iflytop/core/spdlog/include/spdlog/fmt/fmt.h b/appdep/iflytop/core/spdlog/include/spdlog/fmt/fmt.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/fmt/fmt.h rename to appdep/iflytop/core/spdlog/include/spdlog/fmt/fmt.h diff --git a/src/iflytop/core/spdlog/include/spdlog/fmt/ostr.h b/appdep/iflytop/core/spdlog/include/spdlog/fmt/ostr.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/fmt/ostr.h rename to appdep/iflytop/core/spdlog/include/spdlog/fmt/ostr.h diff --git a/src/iflytop/core/spdlog/include/spdlog/fmt/ranges.h b/appdep/iflytop/core/spdlog/include/spdlog/fmt/ranges.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/fmt/ranges.h rename to appdep/iflytop/core/spdlog/include/spdlog/fmt/ranges.h diff --git a/src/iflytop/core/spdlog/include/spdlog/fmt/xchar.h b/appdep/iflytop/core/spdlog/include/spdlog/fmt/xchar.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/fmt/xchar.h rename to appdep/iflytop/core/spdlog/include/spdlog/fmt/xchar.h diff --git a/src/iflytop/core/spdlog/include/spdlog/formatter.h b/appdep/iflytop/core/spdlog/include/spdlog/formatter.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/formatter.h rename to appdep/iflytop/core/spdlog/include/spdlog/formatter.h diff --git a/src/iflytop/core/spdlog/include/spdlog/fwd.h b/appdep/iflytop/core/spdlog/include/spdlog/fwd.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/fwd.h rename to appdep/iflytop/core/spdlog/include/spdlog/fwd.h diff --git a/src/iflytop/core/spdlog/include/spdlog/logger-inl.h b/appdep/iflytop/core/spdlog/include/spdlog/logger-inl.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/logger-inl.h rename to appdep/iflytop/core/spdlog/include/spdlog/logger-inl.h diff --git a/src/iflytop/core/spdlog/include/spdlog/logger.h b/appdep/iflytop/core/spdlog/include/spdlog/logger.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/logger.h rename to appdep/iflytop/core/spdlog/include/spdlog/logger.h diff --git a/src/iflytop/core/spdlog/include/spdlog/pattern_formatter-inl.h b/appdep/iflytop/core/spdlog/include/spdlog/pattern_formatter-inl.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/pattern_formatter-inl.h rename to appdep/iflytop/core/spdlog/include/spdlog/pattern_formatter-inl.h diff --git a/src/iflytop/core/spdlog/include/spdlog/pattern_formatter.h b/appdep/iflytop/core/spdlog/include/spdlog/pattern_formatter.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/pattern_formatter.h rename to appdep/iflytop/core/spdlog/include/spdlog/pattern_formatter.h diff --git a/src/iflytop/core/spdlog/include/spdlog/sinks/android_sink.h b/appdep/iflytop/core/spdlog/include/spdlog/sinks/android_sink.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/sinks/android_sink.h rename to appdep/iflytop/core/spdlog/include/spdlog/sinks/android_sink.h diff --git a/src/iflytop/core/spdlog/include/spdlog/sinks/ansicolor_sink-inl.h b/appdep/iflytop/core/spdlog/include/spdlog/sinks/ansicolor_sink-inl.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/sinks/ansicolor_sink-inl.h rename to appdep/iflytop/core/spdlog/include/spdlog/sinks/ansicolor_sink-inl.h diff --git a/src/iflytop/core/spdlog/include/spdlog/sinks/ansicolor_sink.h b/appdep/iflytop/core/spdlog/include/spdlog/sinks/ansicolor_sink.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/sinks/ansicolor_sink.h rename to appdep/iflytop/core/spdlog/include/spdlog/sinks/ansicolor_sink.h diff --git a/src/iflytop/core/spdlog/include/spdlog/sinks/base_sink-inl.h b/appdep/iflytop/core/spdlog/include/spdlog/sinks/base_sink-inl.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/sinks/base_sink-inl.h rename to appdep/iflytop/core/spdlog/include/spdlog/sinks/base_sink-inl.h diff --git a/src/iflytop/core/spdlog/include/spdlog/sinks/base_sink.h b/appdep/iflytop/core/spdlog/include/spdlog/sinks/base_sink.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/sinks/base_sink.h rename to appdep/iflytop/core/spdlog/include/spdlog/sinks/base_sink.h diff --git a/src/iflytop/core/spdlog/include/spdlog/sinks/basic_file_sink-inl.h b/appdep/iflytop/core/spdlog/include/spdlog/sinks/basic_file_sink-inl.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/sinks/basic_file_sink-inl.h rename to appdep/iflytop/core/spdlog/include/spdlog/sinks/basic_file_sink-inl.h diff --git a/src/iflytop/core/spdlog/include/spdlog/sinks/basic_file_sink.h b/appdep/iflytop/core/spdlog/include/spdlog/sinks/basic_file_sink.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/sinks/basic_file_sink.h rename to appdep/iflytop/core/spdlog/include/spdlog/sinks/basic_file_sink.h diff --git a/src/iflytop/core/spdlog/include/spdlog/sinks/daily_file_sink.h b/appdep/iflytop/core/spdlog/include/spdlog/sinks/daily_file_sink.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/sinks/daily_file_sink.h rename to appdep/iflytop/core/spdlog/include/spdlog/sinks/daily_file_sink.h diff --git a/src/iflytop/core/spdlog/include/spdlog/sinks/dist_sink.h b/appdep/iflytop/core/spdlog/include/spdlog/sinks/dist_sink.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/sinks/dist_sink.h rename to appdep/iflytop/core/spdlog/include/spdlog/sinks/dist_sink.h diff --git a/src/iflytop/core/spdlog/include/spdlog/sinks/dup_filter_sink.h b/appdep/iflytop/core/spdlog/include/spdlog/sinks/dup_filter_sink.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/sinks/dup_filter_sink.h rename to appdep/iflytop/core/spdlog/include/spdlog/sinks/dup_filter_sink.h diff --git a/src/iflytop/core/spdlog/include/spdlog/sinks/hourly_file_sink.h b/appdep/iflytop/core/spdlog/include/spdlog/sinks/hourly_file_sink.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/sinks/hourly_file_sink.h rename to appdep/iflytop/core/spdlog/include/spdlog/sinks/hourly_file_sink.h diff --git a/src/iflytop/core/spdlog/include/spdlog/sinks/mongo_sink.h b/appdep/iflytop/core/spdlog/include/spdlog/sinks/mongo_sink.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/sinks/mongo_sink.h rename to appdep/iflytop/core/spdlog/include/spdlog/sinks/mongo_sink.h diff --git a/src/iflytop/core/spdlog/include/spdlog/sinks/msvc_sink.h b/appdep/iflytop/core/spdlog/include/spdlog/sinks/msvc_sink.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/sinks/msvc_sink.h rename to appdep/iflytop/core/spdlog/include/spdlog/sinks/msvc_sink.h diff --git a/src/iflytop/core/spdlog/include/spdlog/sinks/null_sink.h b/appdep/iflytop/core/spdlog/include/spdlog/sinks/null_sink.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/sinks/null_sink.h rename to appdep/iflytop/core/spdlog/include/spdlog/sinks/null_sink.h diff --git a/src/iflytop/core/spdlog/include/spdlog/sinks/ostream_sink.h b/appdep/iflytop/core/spdlog/include/spdlog/sinks/ostream_sink.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/sinks/ostream_sink.h rename to appdep/iflytop/core/spdlog/include/spdlog/sinks/ostream_sink.h diff --git a/src/iflytop/core/spdlog/include/spdlog/sinks/qt_sinks.h b/appdep/iflytop/core/spdlog/include/spdlog/sinks/qt_sinks.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/sinks/qt_sinks.h rename to appdep/iflytop/core/spdlog/include/spdlog/sinks/qt_sinks.h diff --git a/src/iflytop/core/spdlog/include/spdlog/sinks/ringbuffer_sink.h b/appdep/iflytop/core/spdlog/include/spdlog/sinks/ringbuffer_sink.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/sinks/ringbuffer_sink.h rename to appdep/iflytop/core/spdlog/include/spdlog/sinks/ringbuffer_sink.h diff --git a/src/iflytop/core/spdlog/include/spdlog/sinks/rotating_file_sink-inl.h b/appdep/iflytop/core/spdlog/include/spdlog/sinks/rotating_file_sink-inl.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/sinks/rotating_file_sink-inl.h rename to appdep/iflytop/core/spdlog/include/spdlog/sinks/rotating_file_sink-inl.h diff --git a/src/iflytop/core/spdlog/include/spdlog/sinks/rotating_file_sink.h b/appdep/iflytop/core/spdlog/include/spdlog/sinks/rotating_file_sink.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/sinks/rotating_file_sink.h rename to appdep/iflytop/core/spdlog/include/spdlog/sinks/rotating_file_sink.h diff --git a/src/iflytop/core/spdlog/include/spdlog/sinks/sink-inl.h b/appdep/iflytop/core/spdlog/include/spdlog/sinks/sink-inl.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/sinks/sink-inl.h rename to appdep/iflytop/core/spdlog/include/spdlog/sinks/sink-inl.h diff --git a/src/iflytop/core/spdlog/include/spdlog/sinks/sink.h b/appdep/iflytop/core/spdlog/include/spdlog/sinks/sink.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/sinks/sink.h rename to appdep/iflytop/core/spdlog/include/spdlog/sinks/sink.h diff --git a/src/iflytop/core/spdlog/include/spdlog/sinks/stdout_color_sinks-inl.h b/appdep/iflytop/core/spdlog/include/spdlog/sinks/stdout_color_sinks-inl.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/sinks/stdout_color_sinks-inl.h rename to appdep/iflytop/core/spdlog/include/spdlog/sinks/stdout_color_sinks-inl.h diff --git a/src/iflytop/core/spdlog/include/spdlog/sinks/stdout_color_sinks.h b/appdep/iflytop/core/spdlog/include/spdlog/sinks/stdout_color_sinks.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/sinks/stdout_color_sinks.h rename to appdep/iflytop/core/spdlog/include/spdlog/sinks/stdout_color_sinks.h diff --git a/src/iflytop/core/spdlog/include/spdlog/sinks/stdout_sinks-inl.h b/appdep/iflytop/core/spdlog/include/spdlog/sinks/stdout_sinks-inl.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/sinks/stdout_sinks-inl.h rename to appdep/iflytop/core/spdlog/include/spdlog/sinks/stdout_sinks-inl.h diff --git a/src/iflytop/core/spdlog/include/spdlog/sinks/stdout_sinks.h b/appdep/iflytop/core/spdlog/include/spdlog/sinks/stdout_sinks.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/sinks/stdout_sinks.h rename to appdep/iflytop/core/spdlog/include/spdlog/sinks/stdout_sinks.h diff --git a/src/iflytop/core/spdlog/include/spdlog/sinks/syslog_sink.h b/appdep/iflytop/core/spdlog/include/spdlog/sinks/syslog_sink.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/sinks/syslog_sink.h rename to appdep/iflytop/core/spdlog/include/spdlog/sinks/syslog_sink.h diff --git a/src/iflytop/core/spdlog/include/spdlog/sinks/systemd_sink.h b/appdep/iflytop/core/spdlog/include/spdlog/sinks/systemd_sink.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/sinks/systemd_sink.h rename to appdep/iflytop/core/spdlog/include/spdlog/sinks/systemd_sink.h diff --git a/src/iflytop/core/spdlog/include/spdlog/sinks/tcp_sink.h b/appdep/iflytop/core/spdlog/include/spdlog/sinks/tcp_sink.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/sinks/tcp_sink.h rename to appdep/iflytop/core/spdlog/include/spdlog/sinks/tcp_sink.h diff --git a/src/iflytop/core/spdlog/include/spdlog/sinks/udp_sink.h b/appdep/iflytop/core/spdlog/include/spdlog/sinks/udp_sink.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/sinks/udp_sink.h rename to appdep/iflytop/core/spdlog/include/spdlog/sinks/udp_sink.h diff --git a/src/iflytop/core/spdlog/include/spdlog/sinks/win_eventlog_sink.h b/appdep/iflytop/core/spdlog/include/spdlog/sinks/win_eventlog_sink.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/sinks/win_eventlog_sink.h rename to appdep/iflytop/core/spdlog/include/spdlog/sinks/win_eventlog_sink.h diff --git a/src/iflytop/core/spdlog/include/spdlog/sinks/wincolor_sink-inl.h b/appdep/iflytop/core/spdlog/include/spdlog/sinks/wincolor_sink-inl.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/sinks/wincolor_sink-inl.h rename to appdep/iflytop/core/spdlog/include/spdlog/sinks/wincolor_sink-inl.h diff --git a/src/iflytop/core/spdlog/include/spdlog/sinks/wincolor_sink.h b/appdep/iflytop/core/spdlog/include/spdlog/sinks/wincolor_sink.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/sinks/wincolor_sink.h rename to appdep/iflytop/core/spdlog/include/spdlog/sinks/wincolor_sink.h diff --git a/src/iflytop/core/spdlog/include/spdlog/spdlog-inl.h b/appdep/iflytop/core/spdlog/include/spdlog/spdlog-inl.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/spdlog-inl.h rename to appdep/iflytop/core/spdlog/include/spdlog/spdlog-inl.h diff --git a/src/iflytop/core/spdlog/include/spdlog/spdlog.h b/appdep/iflytop/core/spdlog/include/spdlog/spdlog.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/spdlog.h rename to appdep/iflytop/core/spdlog/include/spdlog/spdlog.h diff --git a/src/iflytop/core/spdlog/include/spdlog/stopwatch.h b/appdep/iflytop/core/spdlog/include/spdlog/stopwatch.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/stopwatch.h rename to appdep/iflytop/core/spdlog/include/spdlog/stopwatch.h diff --git a/src/iflytop/core/spdlog/include/spdlog/tweakme.h b/appdep/iflytop/core/spdlog/include/spdlog/tweakme.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/tweakme.h rename to appdep/iflytop/core/spdlog/include/spdlog/tweakme.h diff --git a/src/iflytop/core/spdlog/include/spdlog/version.h b/appdep/iflytop/core/spdlog/include/spdlog/version.h similarity index 100% rename from src/iflytop/core/spdlog/include/spdlog/version.h rename to appdep/iflytop/core/spdlog/include/spdlog/version.h diff --git a/src/iflytop/core/spdlog/version b/appdep/iflytop/core/spdlog/version similarity index 100% rename from src/iflytop/core/spdlog/version rename to appdep/iflytop/core/spdlog/version diff --git a/src/iflytop/core/spdlogfactory/default_logger_config.hpp b/appdep/iflytop/core/spdlogfactory/default_logger_config.hpp similarity index 100% rename from src/iflytop/core/spdlogfactory/default_logger_config.hpp rename to appdep/iflytop/core/spdlogfactory/default_logger_config.hpp diff --git a/src/iflytop/core/spdlogfactory/logger.hpp b/appdep/iflytop/core/spdlogfactory/logger.hpp similarity index 100% rename from src/iflytop/core/spdlogfactory/logger.hpp rename to appdep/iflytop/core/spdlogfactory/logger.hpp diff --git a/src/iflytop/core/spdlogfactory/logger_factory.cpp b/appdep/iflytop/core/spdlogfactory/logger_factory.cpp similarity index 100% rename from src/iflytop/core/spdlogfactory/logger_factory.cpp rename to appdep/iflytop/core/spdlogfactory/logger_factory.cpp diff --git a/src/iflytop/core/spdlogfactory/logger_factory.hpp b/appdep/iflytop/core/spdlogfactory/logger_factory.hpp similarity index 100% rename from src/iflytop/core/spdlogfactory/logger_factory.hpp rename to appdep/iflytop/core/spdlogfactory/logger_factory.hpp diff --git a/src/iflytop/core/thread/thread.cpp b/appdep/iflytop/core/thread/thread.cpp similarity index 100% rename from src/iflytop/core/thread/thread.cpp rename to appdep/iflytop/core/thread/thread.cpp diff --git a/src/iflytop/core/thread/thread.hpp b/appdep/iflytop/core/thread/thread.hpp similarity index 100% rename from src/iflytop/core/thread/thread.hpp rename to appdep/iflytop/core/thread/thread.hpp diff --git a/src/iflytop/core/utils/base64.hpp b/appdep/iflytop/core/utils/base64.hpp similarity index 100% rename from src/iflytop/core/utils/base64.hpp rename to appdep/iflytop/core/utils/base64.hpp diff --git a/src/iflytop/core/utils/uuid/sole/LICENSE b/appdep/iflytop/core/utils/uuid/sole/LICENSE similarity index 100% rename from src/iflytop/core/utils/uuid/sole/LICENSE rename to appdep/iflytop/core/utils/uuid/sole/LICENSE diff --git a/src/iflytop/core/utils/uuid/sole/README.md b/appdep/iflytop/core/utils/uuid/sole/README.md similarity index 100% rename from src/iflytop/core/utils/uuid/sole/README.md rename to appdep/iflytop/core/utils/uuid/sole/README.md diff --git a/src/iflytop/core/utils/uuid/sole/RELEASE b/appdep/iflytop/core/utils/uuid/sole/RELEASE similarity index 100% rename from src/iflytop/core/utils/uuid/sole/RELEASE rename to appdep/iflytop/core/utils/uuid/sole/RELEASE diff --git a/src/iflytop/core/utils/uuid/sole/sole.hpp b/appdep/iflytop/core/utils/uuid/sole/sole.hpp similarity index 100% rename from src/iflytop/core/utils/uuid/sole/sole.hpp rename to appdep/iflytop/core/utils/uuid/sole/sole.hpp diff --git a/src/iflytop/core/utils/uuid/uuid.hpp b/appdep/iflytop/core/utils/uuid/uuid.hpp similarity index 100% rename from src/iflytop/core/utils/uuid/uuid.hpp rename to appdep/iflytop/core/utils/uuid/uuid.hpp diff --git a/src/iflytop/core/zexception/zexception.cpp b/appdep/iflytop/core/zexception/zexception.cpp similarity index 100% rename from src/iflytop/core/zexception/zexception.cpp rename to appdep/iflytop/core/zexception/zexception.cpp diff --git a/src/iflytop/core/zexception/zexception.hpp b/appdep/iflytop/core/zexception/zexception.hpp similarity index 100% rename from src/iflytop/core/zexception/zexception.hpp rename to appdep/iflytop/core/zexception/zexception.hpp diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXBase64.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXBase64.h new file mode 100644 index 0000000..cdfdc04 --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXBase64.h @@ -0,0 +1,124 @@ +#ifndef _MACARON_BASE64_H_ +#define _MACARON_BASE64_H_ + +/** + * The MIT License (MIT) + * Copyright (c) 2016 tomykaira + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include + +namespace macaron { + +class Base64 { + public: + + static std::string Encode(const std::string data) { + static constexpr char sEncodingTable[] = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '0', '1', '2', '3', + '4', '5', '6', '7', '8', '9', '+', '/' + }; + + size_t in_len = data.size(); + size_t out_len = 4 * ((in_len + 2) / 3); + std::string ret(out_len, '\0'); + size_t i; + char *p = const_cast(ret.c_str()); + + for (i = 0; i < in_len - 2; i += 3) { + *p++ = sEncodingTable[(data[i] >> 2) & 0x3F]; + *p++ = sEncodingTable[((data[i] & 0x3) << 4) | ((int) (data[i + 1] & 0xF0) >> 4)]; + *p++ = sEncodingTable[((data[i + 1] & 0xF) << 2) | ((int) (data[i + 2] & 0xC0) >> 6)]; + *p++ = sEncodingTable[data[i + 2] & 0x3F]; + } + if (i < in_len) { + *p++ = sEncodingTable[(data[i] >> 2) & 0x3F]; + if (i == (in_len - 1)) { + *p++ = sEncodingTable[((data[i] & 0x3) << 4)]; + *p++ = '='; + } + else { + *p++ = sEncodingTable[((data[i] & 0x3) << 4) | ((int) (data[i + 1] & 0xF0) >> 4)]; + *p++ = sEncodingTable[((data[i + 1] & 0xF) << 2)]; + } + *p++ = '='; + } + + return ret; + } + + static std::string Decode(const std::string& input, std::string& out) { + static constexpr unsigned char kDecodingTable[] = { + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64, + 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64, + 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64 + }; + + size_t in_len = input.size(); + if (in_len % 4 != 0) return "Input data size is not a multiple of 4"; + + size_t out_len = in_len / 4 * 3; + if (input[in_len - 1] == '=') out_len--; + if (input[in_len - 2] == '=') out_len--; + + out.resize(out_len); + + for (size_t i = 0, j = 0; i < in_len;) { + uint32_t a = input[i] == '=' ? 0 & i++ : kDecodingTable[static_cast(input[i++])]; + uint32_t b = input[i] == '=' ? 0 & i++ : kDecodingTable[static_cast(input[i++])]; + uint32_t c = input[i] == '=' ? 0 & i++ : kDecodingTable[static_cast(input[i++])]; + uint32_t d = input[i] == '=' ? 0 & i++ : kDecodingTable[static_cast(input[i++])]; + + uint32_t triple = (a << 3 * 6) + (b << 2 * 6) + (c << 1 * 6) + (d << 0 * 6); + + if (j < out_len) out[j++] = (triple >> 2 * 8) & 0xFF; + if (j < out_len) out[j++] = (triple >> 1 * 8) & 0xFF; + if (j < out_len) out[j++] = (triple >> 0 * 8) & 0xFF; + } + + return ""; + } + +}; + +} + +#endif /* _MACARON_BASE64_H_ */ diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXBench.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXBench.h new file mode 100644 index 0000000..c4f904b --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXBench.h @@ -0,0 +1,32 @@ +/* + * IXBench.h + * Author: Benjamin Sergeant + * Copyright (c) 2017-2020 Machine Zone, Inc. All rights reserved. + */ +#pragma once + +#include +#include +#include + +namespace ix +{ + class Bench + { + public: + Bench(const std::string& description); + ~Bench(); + + void reset(); + void record(); + void report(); + void setReported(); + uint64_t getDuration() const; + + private: + std::string _description; + std::chrono::time_point _start; + uint64_t _duration; + bool _reported; + }; +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXCancellationRequest.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXCancellationRequest.h new file mode 100644 index 0000000..8b0547d --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXCancellationRequest.h @@ -0,0 +1,18 @@ +/* + * IXCancellationRequest.h + * Author: Benjamin Sergeant + * Copyright (c) 2018 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include +#include + +namespace ix +{ + using CancellationRequest = std::function; + + CancellationRequest makeCancellationRequestWithTimeout( + int seconds, std::atomic& requestInitCancellation); +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXConnectionState.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXConnectionState.h new file mode 100644 index 0000000..b7530d0 --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXConnectionState.h @@ -0,0 +1,54 @@ +/* + * IXConnectionState.h + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace ix +{ + using OnSetTerminatedCallback = std::function; + + class ConnectionState + { + public: + ConnectionState(); + virtual ~ConnectionState() = default; + + virtual void computeId(); + virtual const std::string& getId() const; + + void setTerminated(); + bool isTerminated() const; + + const std::string& getRemoteIp(); + int getRemotePort(); + + static std::shared_ptr createConnectionState(); + + private: + void setOnSetTerminatedCallback(const OnSetTerminatedCallback& callback); + + void setRemoteIp(const std::string& remoteIp); + void setRemotePort(int remotePort); + + protected: + std::atomic _terminated; + std::string _id; + OnSetTerminatedCallback _onSetTerminatedCallback; + + static std::atomic _globalId; + + std::string _remoteIp; + int _remotePort; + + friend class SocketServer; + }; +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXDNSLookup.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXDNSLookup.h new file mode 100644 index 0000000..fcdd103 --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXDNSLookup.h @@ -0,0 +1,67 @@ +/* + * IXDNSLookup.h + * Author: Benjamin Sergeant + * Copyright (c) 2018 Machine Zone, Inc. All rights reserved. + * + * Resolve a hostname+port to a struct addrinfo obtained with getaddrinfo + * Does this in a background thread so that it can be cancelled, since + * getaddrinfo is a blocking call, and we don't want to block the main thread on Mobile. + */ + +#pragma once + +#include "IXCancellationRequest.h" +#include +#include +#include +#include +#include + +struct addrinfo; + +namespace ix +{ + class DNSLookup : public std::enable_shared_from_this + { + public: + DNSLookup(const std::string& hostname, int port, int64_t wait = DNSLookup::kDefaultWait); + ~DNSLookup() = default; + + struct addrinfo* resolve(std::string& errMsg, + const CancellationRequest& isCancellationRequested, + bool cancellable = true); + + void release(struct addrinfo* addr); + + private: + struct addrinfo* resolveCancellable(std::string& errMsg, + const CancellationRequest& isCancellationRequested); + struct addrinfo* resolveUnCancellable(std::string& errMsg, + const CancellationRequest& isCancellationRequested); + + static struct addrinfo* getAddrInfo(const std::string& hostname, + int port, + std::string& errMsg); + + void run(std::weak_ptr self, std::string hostname, int port); // thread runner + + void setErrMsg(const std::string& errMsg); + const std::string& getErrMsg(); + + void setRes(struct addrinfo* addr); + struct addrinfo* getRes(); + + std::string _hostname; + int _port; + int64_t _wait; + const static int64_t kDefaultWait; + + struct addrinfo* _res; + std::mutex _resMutex; + + std::string _errMsg; + std::mutex _errMsgMutex; + + std::atomic _done; + }; +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXExponentialBackoff.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXExponentialBackoff.h new file mode 100644 index 0000000..79e19e9 --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXExponentialBackoff.h @@ -0,0 +1,16 @@ +/* + * IXExponentialBackoff.h + * Author: Benjamin Sergeant + * Copyright (c) 2017-2019 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include + +namespace ix +{ + uint32_t calculateRetryWaitMilliseconds(uint32_t retryCount, + uint32_t maxWaitBetweenReconnectionRetries, + uint32_t minWaitBetweenReconnectionRetries); +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXGetFreePort.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXGetFreePort.h new file mode 100644 index 0000000..868faf5 --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXGetFreePort.h @@ -0,0 +1,12 @@ +/* + * IXGetFreePort.h + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone. All rights reserved. + */ + +#pragma once + +namespace ix +{ + int getFreePort(); +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXGzipCodec.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXGzipCodec.h new file mode 100644 index 0000000..8a5fc11 --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXGzipCodec.h @@ -0,0 +1,15 @@ +/* + * IXGzipCodec.h + * Author: Benjamin Sergeant + * Copyright (c) 2020 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include + +namespace ix +{ + std::string gzipCompress(const std::string& str); + bool gzipDecompress(const std::string& in, std::string& out); +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXHttp.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXHttp.h new file mode 100644 index 0000000..2cf4f29 --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXHttp.h @@ -0,0 +1,134 @@ +/* + * IXHttp.h + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include "IXProgressCallback.h" +#include "IXWebSocketHttpHeaders.h" +#include +#include +#include + +namespace ix +{ + enum class HttpErrorCode : int + { + Ok = 0, + CannotConnect = 1, + Timeout = 2, + Gzip = 3, + UrlMalformed = 4, + CannotCreateSocket = 5, + SendError = 6, + ReadError = 7, + CannotReadStatusLine = 8, + MissingStatus = 9, + HeaderParsingError = 10, + MissingLocation = 11, + TooManyRedirects = 12, + ChunkReadError = 13, + CannotReadBody = 14, + Cancelled = 15, + Invalid = 100 + }; + + struct HttpResponse + { + int statusCode; + std::string description; + HttpErrorCode errorCode; + WebSocketHttpHeaders headers; + std::string body; + std::string errorMsg; + uint64_t uploadSize; + uint64_t downloadSize; + + HttpResponse(int s = 0, + const std::string& des = std::string(), + const HttpErrorCode& c = HttpErrorCode::Ok, + const WebSocketHttpHeaders& h = WebSocketHttpHeaders(), + const std::string& b = std::string(), + const std::string& e = std::string(), + uint64_t u = 0, + uint64_t d = 0) + : statusCode(s) + , description(des) + , errorCode(c) + , headers(h) + , body(b) + , errorMsg(e) + , uploadSize(u) + , downloadSize(d) + { + ; + } + }; + + using HttpResponsePtr = std::shared_ptr; + using HttpParameters = std::unordered_map; + using HttpFormDataParameters = std::unordered_map; + using Logger = std::function; + using OnResponseCallback = std::function; + + struct HttpRequestArgs + { + std::string url; + std::string verb; + WebSocketHttpHeaders extraHeaders; + std::string body; + std::string multipartBoundary; + int connectTimeout = 60; + int transferTimeout = 1800; + bool followRedirects = true; + int maxRedirects = 5; + bool verbose = false; + bool compress = true; + bool compressRequest = false; + Logger logger; + OnProgressCallback onProgressCallback; + OnChunkCallback onChunkCallback; + std::atomic cancel; + }; + + using HttpRequestArgsPtr = std::shared_ptr; + + struct HttpRequest + { + std::string uri; + std::string method; + std::string version; + std::string body; + WebSocketHttpHeaders headers; + + HttpRequest(const std::string& u, + const std::string& m, + const std::string& v, + const std::string& b, + const WebSocketHttpHeaders& h = WebSocketHttpHeaders()) + : uri(u) + , method(m) + , version(v) + , body(b) + , headers(h) + { + } + }; + + using HttpRequestPtr = std::shared_ptr; + + class Http + { + public: + static std::tuple parseRequest( + std::unique_ptr& socket, int timeoutSecs); + static bool sendResponse(HttpResponsePtr response, std::unique_ptr& socket); + + static std::pair parseStatusLine(const std::string& line); + static std::tuple parseRequestLine( + const std::string& line); + static std::string trim(const std::string& str); + }; +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXHttpClient.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXHttpClient.h new file mode 100644 index 0000000..c4b0584 --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXHttpClient.h @@ -0,0 +1,123 @@ +/* + * IXHttpClient.h + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include "IXHttp.h" +#include "IXSocket.h" +#include "IXSocketTLSOptions.h" +#include "IXWebSocketHttpHeaders.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace ix +{ + class HttpClient + { + public: + HttpClient(bool async = false); + ~HttpClient(); + + HttpResponsePtr get(const std::string& url, HttpRequestArgsPtr args); + HttpResponsePtr head(const std::string& url, HttpRequestArgsPtr args); + HttpResponsePtr Delete(const std::string& url, HttpRequestArgsPtr args); + + HttpResponsePtr post(const std::string& url, + const HttpParameters& httpParameters, + const HttpFormDataParameters& httpFormDataParameters, + HttpRequestArgsPtr args); + HttpResponsePtr post(const std::string& url, + const std::string& body, + HttpRequestArgsPtr args); + + HttpResponsePtr put(const std::string& url, + const HttpParameters& httpParameters, + const HttpFormDataParameters& httpFormDataParameters, + HttpRequestArgsPtr args); + HttpResponsePtr put(const std::string& url, + const std::string& body, + HttpRequestArgsPtr args); + + HttpResponsePtr patch(const std::string& url, + const HttpParameters& httpParameters, + const HttpFormDataParameters& httpFormDataParameters, + HttpRequestArgsPtr args); + HttpResponsePtr patch(const std::string& url, + const std::string& body, + HttpRequestArgsPtr args); + + HttpResponsePtr request(const std::string& url, + const std::string& verb, + const std::string& body, + HttpRequestArgsPtr args, + int redirects = 0); + + HttpResponsePtr request(const std::string& url, + const std::string& verb, + const HttpParameters& httpParameters, + const HttpFormDataParameters& httpFormDataParameters, + HttpRequestArgsPtr args); + + void setForceBody(bool value); + + // Async API + HttpRequestArgsPtr createRequest(const std::string& url = std::string(), + const std::string& verb = HttpClient::kGet); + + bool performRequest(HttpRequestArgsPtr request, + const OnResponseCallback& onResponseCallback); + + // TLS + void setTLSOptions(const SocketTLSOptions& tlsOptions); + + std::string serializeHttpParameters(const HttpParameters& httpParameters); + + std::string serializeHttpFormDataParameters( + const std::string& multipartBoundary, + const HttpFormDataParameters& httpFormDataParameters, + const HttpParameters& httpParameters = HttpParameters()); + + std::string generateMultipartBoundary(); + + std::string urlEncode(const std::string& value); + + const static std::string kPost; + const static std::string kGet; + const static std::string kHead; + const static std::string kDelete; + const static std::string kPut; + const static std::string kPatch; + + private: + void log(const std::string& msg, HttpRequestArgsPtr args); + + // Async API background thread runner + void run(); + // Async API + bool _async; + std::queue> _queue; + mutable std::mutex _queueMutex; + std::condition_variable _condition; + std::atomic _stop; + std::thread _thread; + + std::unique_ptr _socket; + std::recursive_mutex _mutex; // to protect accessing the _socket (only one socket per + // client) the mutex needs to be recursive as this function + // might be called recursively to follow HTTP redirections + + SocketTLSOptions _tlsOptions; + + bool _forceBody; + }; +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXHttpServer.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXHttpServer.h new file mode 100644 index 0000000..7de6763 --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXHttpServer.h @@ -0,0 +1,59 @@ +/* + * IXHttpServer.h + * Author: Benjamin Sergeant + * Copyright (c) 2018 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include "IXHttp.h" +#include "IXSocketServer.h" +#include "IXWebSocket.h" +#include +#include +#include +#include +#include +#include +#include // pair + +namespace ix +{ + class HttpServer final : public SocketServer + { + public: + using OnConnectionCallback = + std::function)>; + + HttpServer(int port = SocketServer::kDefaultPort, + const std::string& host = SocketServer::kDefaultHost, + int backlog = SocketServer::kDefaultTcpBacklog, + size_t maxConnections = SocketServer::kDefaultMaxConnections, + int addressFamily = SocketServer::kDefaultAddressFamily, + int timeoutSecs = HttpServer::kDefaultTimeoutSecs); + virtual ~HttpServer(); + virtual void stop() final; + + void setOnConnectionCallback(const OnConnectionCallback& callback); + + void makeRedirectServer(const std::string& redirectUrl); + + void makeDebugServer(); + + int getTimeoutSecs(); + private: + // Member variables + OnConnectionCallback _onConnectionCallback; + std::atomic _connectedClientsCount; + + const static int kDefaultTimeoutSecs; + int _timeoutSecs; + + // Methods + virtual void handleConnection(std::unique_ptr, + std::shared_ptr connectionState) final; + virtual size_t getConnectedClientsCount() final; + + void setDefaultConnectionCallback(); + }; +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXNetSystem.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXNetSystem.h new file mode 100644 index 0000000..9639544 --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXNetSystem.h @@ -0,0 +1,87 @@ +/* + * IXNetSystem.h + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone. All rights reserved. + */ + +#pragma once + +#ifdef _WIN32 + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif + +#include +#include +#include +#include +#include +#include + +#undef EWOULDBLOCK +#undef EAGAIN +#undef EINPROGRESS +#undef EBADF +#undef EINVAL + +// map to WSA error codes +#define EWOULDBLOCK WSAEWOULDBLOCK +#define EAGAIN WSATRY_AGAIN +#define EINPROGRESS WSAEINPROGRESS +#define EBADF WSAEBADF +#define EINVAL WSAEINVAL + +// Define our own poll on Windows, as a wrapper on top of select +typedef unsigned long int nfds_t; + +// pollfd is not defined by some versions of mingw64 since _WIN32_WINNT is too low +#if _WIN32_WINNT < 0x0600 +struct pollfd +{ + int fd; /* file descriptor */ + short events; /* requested events */ + short revents; /* returned events */ +}; + +#define POLLIN 0x001 /* There is data to read. */ +#define POLLOUT 0x004 /* Writing now will not block. */ +#define POLLERR 0x008 /* Error condition. */ +#define POLLHUP 0x010 /* Hung up. */ +#define POLLNVAL 0x020 /* Invalid polling request. */ +#endif + +#else +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +namespace ix +{ +#ifdef _WIN32 + typedef SOCKET socket_t; +#else + typedef int socket_t; +#endif + + bool initNetSystem(); + bool uninitNetSystem(); + + int poll(struct pollfd* fds, nfds_t nfds, int timeout, void** event); + + const char* inet_ntop(int af, const void* src, char* dst, socklen_t size); + int inet_pton(int af, const char* src, void* dst); + + unsigned short network_to_host_short(unsigned short value); +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXProgressCallback.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXProgressCallback.h new file mode 100644 index 0000000..3dfccc9 --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXProgressCallback.h @@ -0,0 +1,16 @@ +/* + * IXProgressCallback.h + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include +#include + +namespace ix +{ + using OnProgressCallback = std::function; + using OnChunkCallback = std::function; +} diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXSelectInterrupt.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXSelectInterrupt.h new file mode 100644 index 0000000..de6db12 --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXSelectInterrupt.h @@ -0,0 +1,35 @@ +/* + * IXSelectInterrupt.h + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include +#include +#include + +namespace ix +{ + class SelectInterrupt + { + public: + SelectInterrupt(); + virtual ~SelectInterrupt(); + + virtual bool init(std::string& errorMsg); + + virtual bool notify(uint64_t value); + virtual bool clear(); + virtual uint64_t read(); + virtual int getFd() const; + virtual void* getEvent() const; + + // Used as special codes for pipe communication + static const uint64_t kSendRequest; + static const uint64_t kCloseRequest; + }; + + using SelectInterruptPtr = std::unique_ptr; +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXSelectInterruptEvent.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXSelectInterruptEvent.h new file mode 100644 index 0000000..d965661 --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXSelectInterruptEvent.h @@ -0,0 +1,39 @@ +/* + * IXSelectInterruptEvent.h + */ + +#pragma once + +#include "IXSelectInterrupt.h" +#include +#include +#include +#include +#ifdef _WIN32 +#include +#endif + +namespace ix +{ + class SelectInterruptEvent final : public SelectInterrupt + { + public: + SelectInterruptEvent(); + virtual ~SelectInterruptEvent(); + + bool init(std::string& /*errorMsg*/) final; + + bool notify(uint64_t value) final; + bool clear() final; + uint64_t read() final; + void* getEvent() const final; + private: + // contains every value only once, new values are inserted at the begin, nu + std::deque _values; + std::mutex _valuesMutex; +#ifdef _WIN32 + // Windows Event to wake up the socket poll + HANDLE _event; +#endif + }; +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXSelectInterruptFactory.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXSelectInterruptFactory.h new file mode 100644 index 0000000..5faf1d6 --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXSelectInterruptFactory.h @@ -0,0 +1,16 @@ +/* + * IXSelectInterruptFactory.h + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include + +namespace ix +{ + class SelectInterrupt; + using SelectInterruptPtr = std::unique_ptr; + SelectInterruptPtr createSelectInterrupt(); +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXSelectInterruptPipe.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXSelectInterruptPipe.h new file mode 100644 index 0000000..7668915 --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXSelectInterruptPipe.h @@ -0,0 +1,40 @@ +/* + * IXSelectInterruptPipe.h + * Author: Benjamin Sergeant + * Copyright (c) 2018-2019 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include "IXSelectInterrupt.h" +#include +#include +#include + +namespace ix +{ + class SelectInterruptPipe final : public SelectInterrupt + { + public: + SelectInterruptPipe(); + virtual ~SelectInterruptPipe(); + + bool init(std::string& errorMsg) final; + + bool notify(uint64_t value) final; + bool clear() final; + uint64_t read() final; + int getFd() const final; + + private: + // Store file descriptors used by the communication pipe. Communication + // happens between a control thread and a background thread, which is + // blocked on select. + int _fildes[2]; + mutable std::mutex _fildesMutex; + + // Used to identify the read/write idx + static const int kPipeReadIndex; + static const int kPipeWriteIndex; + }; +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXSetThreadName.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXSetThreadName.h new file mode 100644 index 0000000..de57c4a --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXSetThreadName.h @@ -0,0 +1,12 @@ +/* + * IXSetThreadName.h + * Author: Benjamin Sergeant + * Copyright (c) 2018 Machine Zone, Inc. All rights reserved. + */ +#pragma once +#include + +namespace ix +{ + void setThreadName(const std::string& name); +} diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXSocket.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXSocket.h new file mode 100644 index 0000000..d1fa969 --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXSocket.h @@ -0,0 +1,99 @@ +/* + * IXSocket.h + * Author: Benjamin Sergeant + * Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#ifdef _MSC_VER +typedef SSIZE_T ssize_t; +#endif +#endif + +#include "IXCancellationRequest.h" +#include "IXProgressCallback.h" +#include "IXSelectInterrupt.h" + +namespace ix +{ + enum class PollResultType + { + ReadyForRead = 0, + ReadyForWrite = 1, + Timeout = 2, + Error = 3, + SendRequest = 4, + CloseRequest = 5 + }; + + class Socket + { + public: + Socket(int fd = -1); + virtual ~Socket(); + bool init(std::string& errorMsg); + + // Functions to check whether there is activity on the socket + PollResultType poll(int timeoutMs = kDefaultPollTimeout); + bool wakeUpFromPoll(uint64_t wakeUpCode); + bool isWakeUpFromPollSupported(); + + PollResultType isReadyToWrite(int timeoutMs); + PollResultType isReadyToRead(int timeoutMs); + + // Virtual methods + virtual bool accept(std::string& errMsg); + + virtual bool connect(const std::string& host, + int port, + std::string& errMsg, + const CancellationRequest& isCancellationRequested); + virtual void close(); + + virtual ssize_t send(char* buffer, size_t length); + ssize_t send(const std::string& buffer); + virtual ssize_t recv(void* buffer, size_t length); + + // Blocking and cancellable versions, working with socket that can be set + // to non blocking mode. Used during HTTP upgrade. + bool readByte(void* buffer, const CancellationRequest& isCancellationRequested); + bool writeBytes(const std::string& str, const CancellationRequest& isCancellationRequested); + + std::pair readLine(const CancellationRequest& isCancellationRequested); + std::pair readBytes(size_t length, + const OnProgressCallback& onProgressCallback, + const OnChunkCallback& onChunkCallback, + const CancellationRequest& isCancellationRequested); + + static int getErrno(); + static bool isWaitNeeded(); + static void closeSocket(int fd); + + static PollResultType poll(bool readyToRead, + int timeoutMs, + int sockfd, + const SelectInterruptPtr& selectInterrupt); + + protected: + std::atomic _sockfd; + std::mutex _socketMutex; + + static bool readSelectInterruptRequest(const SelectInterruptPtr& selectInterrupt, + PollResultType* pollResult); + + private: + static const int kDefaultPollTimeout; + static const int kDefaultPollNoTimeout; + + SelectInterruptPtr _selectInterrupt; + }; +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXSocketConnect.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXSocketConnect.h new file mode 100644 index 0000000..84a0858 --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXSocketConnect.h @@ -0,0 +1,31 @@ +/* + * IXSocketConnect.h + * Author: Benjamin Sergeant + * Copyright (c) 2018 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include "IXCancellationRequest.h" +#include + +struct addrinfo; + +namespace ix +{ + class SocketConnect + { + public: + static int connect(const std::string& hostname, + int port, + std::string& errMsg, + const CancellationRequest& isCancellationRequested); + + static void configure(int sockfd); + + private: + static int connectToAddress(const struct addrinfo* address, + std::string& errMsg, + const CancellationRequest& isCancellationRequested); + }; +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXSocketFactory.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXSocketFactory.h new file mode 100644 index 0000000..de1eeda --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXSocketFactory.h @@ -0,0 +1,21 @@ + +/* + * IXSocketFactory.h + * Author: Benjamin Sergeant + * Copyright (c) 2018 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include "IXSocketTLSOptions.h" +#include +#include + +namespace ix +{ + class Socket; + std::unique_ptr createSocket(bool tls, + int fd, + std::string& errorMsg, + const SocketTLSOptions& tlsOptions); +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXSocketServer.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXSocketServer.h new file mode 100644 index 0000000..fe0f7e2 --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXSocketServer.h @@ -0,0 +1,130 @@ +/* + * IXSocketServer.h + * Author: Benjamin Sergeant + * Copyright (c) 2018 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include "IXConnectionState.h" +#include "IXNetSystem.h" +#include "IXSelectInterrupt.h" +#include "IXSocketTLSOptions.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // pair + +namespace ix +{ + class Socket; + + class SocketServer + { + public: + using ConnectionStateFactory = std::function()>; + + // Each connection is handled by its own worker thread. + // We use a list as we only care about remove and append operations. + using ConnectionThreads = + std::list, std::thread>>; + + SocketServer(int port = SocketServer::kDefaultPort, + const std::string& host = SocketServer::kDefaultHost, + int backlog = SocketServer::kDefaultTcpBacklog, + size_t maxConnections = SocketServer::kDefaultMaxConnections, + int addressFamily = SocketServer::kDefaultAddressFamily); + virtual ~SocketServer(); + virtual void stop(); + + // It is possible to override ConnectionState through inheritance + // this method allows user to change the factory by returning an object + // that inherits from ConnectionState but has its own methods. + void setConnectionStateFactory(const ConnectionStateFactory& connectionStateFactory); + + const static int kDefaultPort; + const static std::string kDefaultHost; + const static int kDefaultTcpBacklog; + const static size_t kDefaultMaxConnections; + const static int kDefaultAddressFamily; + + void start(); + std::pair listen(); + void wait(); + + void setTLSOptions(const SocketTLSOptions& socketTLSOptions); + + int getPort(); + std::string getHost(); + int getBacklog(); + std::size_t getMaxConnections(); + int getAddressFamily(); + protected: + // Logging + void logError(const std::string& str); + void logInfo(const std::string& str); + + void stopAcceptingConnections(); + + private: + // Member variables + int _port; + std::string _host; + int _backlog; + size_t _maxConnections; + int _addressFamily; + + // socket for accepting connections + socket_t _serverFd; + + std::atomic _stop; + + std::mutex _logMutex; + + // background thread to wait for incoming connections + std::thread _thread; + void run(); + void onSetTerminatedCallback(); + + // background thread to cleanup (join) terminated threads + std::atomic _stopGc; + std::thread _gcThread; + void runGC(); + + // the list of (connectionState, threads) for each connections + ConnectionThreads _connectionsThreads; + std::mutex _connectionsThreadsMutex; + + // used to have the main control thread for a server + // wait for a 'terminate' notification without busy polling + std::condition_variable _conditionVariable; + std::mutex _conditionVariableMutex; + + // the factory to create ConnectionState objects + ConnectionStateFactory _connectionStateFactory; + + virtual void handleConnection(std::unique_ptr, + std::shared_ptr connectionState) = 0; + virtual size_t getConnectedClientsCount() = 0; + + // Returns true if all connection threads are joined + void closeTerminatedThreads(); + size_t getConnectionsThreadsCount(); + + SocketTLSOptions _socketTLSOptions; + + // to wake up from select + SelectInterruptPtr _acceptSelectInterrupt; + + // used by the gc thread, to know that a thread needs to be garbage collected + // as a connection + std::condition_variable _conditionVariableGC; + std::mutex _conditionVariableMutexGC; + }; +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXSocketTLSOptions.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXSocketTLSOptions.h new file mode 100644 index 0000000..e396b38 --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXSocketTLSOptions.h @@ -0,0 +1,54 @@ +/* + * IXSocketTLSOptions.h + * Author: Matt DeBoer + * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include + +namespace ix +{ + struct SocketTLSOptions + { + public: + // check validity of the object + bool isValid() const; + + // the certificate presented to peers + std::string certFile; + + // the key used for signing/encryption + std::string keyFile; + + // the ca certificate (or certificate bundle) file containing + // certificates to be trusted by peers; use 'SYSTEM' to + // leverage the system defaults, use 'NONE' to disable peer verification + std::string caFile = "SYSTEM"; + + // list of ciphers (rsa, etc...) + std::string ciphers = "DEFAULT"; + + // whether tls is enabled, used for server code + bool tls = false; + + bool hasCertAndKey() const; + + bool isUsingSystemDefaults() const; + + bool isUsingInMemoryCAs() const; + + bool isPeerVerifyDisabled() const; + + bool isUsingDefaultCiphers() const; + + const std::string& getErrorMsg() const; + + std::string getDescription() const; + + private: + mutable std::string _errMsg; + mutable bool _validated = false; + }; +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXStrCaseCompare.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXStrCaseCompare.h new file mode 100644 index 0000000..8a55de0 --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXStrCaseCompare.h @@ -0,0 +1,25 @@ +/* + * IXStrCaseCompare.h + * Author: Benjamin Sergeant + * Copyright (c) 2020 Machine Zone. All rights reserved. + */ + +#pragma once + +#include + +namespace ix +{ + struct CaseInsensitiveLess + { + // Case Insensitive compare_less binary function + struct NocaseCompare + { + bool operator()(const unsigned char& c1, const unsigned char& c2) const; + }; + + static bool cmp(const std::string& s1, const std::string& s2); + + bool operator()(const std::string& s1, const std::string& s2) const; + }; +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXUdpSocket.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXUdpSocket.h new file mode 100644 index 0000000..9f54daf --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXUdpSocket.h @@ -0,0 +1,45 @@ +/* + * IXUdpSocket.h + * Author: Benjamin Sergeant + * Copyright (c) 2020 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include +#include +#include + +#ifdef _WIN32 +#include +#ifdef _MSC_VER +typedef SSIZE_T ssize_t; +#endif +#endif + +#include "IXNetSystem.h" + +namespace ix +{ + class UdpSocket + { + public: + UdpSocket(int fd = -1); + ~UdpSocket(); + + // Virtual methods + bool init(const std::string& host, int port, std::string& errMsg); + ssize_t sendto(const std::string& buffer); + ssize_t recvfrom(char* buffer, size_t length); + + void close(); + + static int getErrno(); + static bool isWaitNeeded(); + static void closeSocket(int fd); + + private: + std::atomic _sockfd; + struct sockaddr_in _server; + }; +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXUniquePtr.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXUniquePtr.h new file mode 100644 index 0000000..d88ce9b --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXUniquePtr.h @@ -0,0 +1,18 @@ +/* + * IXUniquePtr.h + * Author: Benjamin Sergeant + * Copyright (c) 2020 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include + +namespace ix +{ + template + std::unique_ptr make_unique(Args&&... args) + { + return std::unique_ptr(new T(std::forward(args)...)); + } +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXUrlParser.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXUrlParser.h new file mode 100644 index 0000000..40e6b6e --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXUrlParser.h @@ -0,0 +1,23 @@ +/* + * IXUrlParser.h + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include + +namespace ix +{ + class UrlParser + { + public: + static bool parse(const std::string& url, + std::string& protocol, + std::string& host, + std::string& path, + std::string& query, + int& port); + }; +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXUserAgent.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXUserAgent.h new file mode 100644 index 0000000..367ba18 --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXUserAgent.h @@ -0,0 +1,14 @@ +/* + * IXUserAgent.h + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include + +namespace ix +{ + std::string userAgent(); +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXUtf8Validator.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXUtf8Validator.h new file mode 100644 index 0000000..bc92c90 --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXUtf8Validator.h @@ -0,0 +1,178 @@ +/* + * The following code is adapted from code originally written by Bjoern + * Hoehrmann . See + * http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details. + * + * The original license: + * + * Copyright (c) 2008-2009 Bjoern Hoehrmann + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* + * IXUtf8Validator.h + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. + * + * From websocketpp. Tiny modifications made for code style, function names etc... + */ + +#pragma once + +#include +#include + +namespace ix +{ + /// State that represents a valid utf8 input sequence + static unsigned int const utf8_accept = 0; + /// State that represents an invalid utf8 input sequence + static unsigned int const utf8_reject = 1; + + /// Lookup table for the UTF8 decode state machine + static uint8_t const utf8d[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1f + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3f + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5f + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7f + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9f + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // a0..bf + 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // c0..df + 0xa, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // e0..ef + 0xb, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // f0..ff + 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2 + 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4 + 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6 + 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, + 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // s7..s8 + }; + + /// Decode the next byte of a UTF8 sequence + /** + * @param [out] state The decoder state to advance + * @param [out] codep The codepoint to fill in + * @param [in] byte The byte to input + * @return The ending state of the decode operation + */ + inline uint32_t decodeNextByte(uint32_t* state, uint32_t* codep, uint8_t byte) + { + uint32_t type = utf8d[byte]; + + *codep = (*state != utf8_accept) ? (byte & 0x3fu) | (*codep << 6) : (0xff >> type) & (byte); + + *state = utf8d[256 + *state * 16 + type]; + return *state; + } + + /// Provides streaming UTF8 validation functionality + class Utf8Validator + { + public: + /// Construct and initialize the validator + Utf8Validator() + : m_state(utf8_accept) + , m_codepoint(0) + { + } + + /// Advance the state of the validator with the next input byte + /** + * @param byte The byte to advance the validation state with + * @return Whether or not the byte resulted in a validation error. + */ + bool consume(uint8_t byte) + { + if (decodeNextByte(&m_state, &m_codepoint, byte) == utf8_reject) + { + return false; + } + return true; + } + + /// Advance Validator state with input from an iterator pair + /** + * @param begin Input iterator to the start of the input range + * @param end Input iterator to the end of the input range + * @return Whether or not decoding the bytes resulted in a validation error. + */ + template + bool decode(iterator_type begin, iterator_type end) + { + for (iterator_type it = begin; it != end; ++it) + { + unsigned int result = + decodeNextByte(&m_state, &m_codepoint, static_cast(*it)); + + if (result == utf8_reject) + { + return false; + } + } + return true; + } + + /// Return whether the input sequence ended on a valid utf8 codepoint + /** + * @return Whether or not the input sequence ended on a valid codepoint. + */ + bool complete() + { + return m_state == utf8_accept; + } + + /// Reset the Validator to decode another message + void reset() + { + m_state = utf8_accept; + m_codepoint = 0; + } + + private: + uint32_t m_state; + uint32_t m_codepoint; + }; + + /// Validate a UTF8 string + /** + * convenience function that creates a Validator, validates a complete string + * and returns the result. + */ + inline bool validateUtf8(std::string const& s) + { + Utf8Validator v; + if (!v.decode(s.begin(), s.end())) + { + return false; + } + return v.complete(); + } + +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXUuid.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXUuid.h new file mode 100644 index 0000000..1000436 --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXUuid.h @@ -0,0 +1,17 @@ +/* + * IXUuid.h + * Author: Benjamin Sergeant + * Copyright (c) 2017 Machine Zone. All rights reserved. + */ +#pragma once + +#include + +namespace ix +{ + /** + * Generate a random uuid + */ + std::string uuid4(); + +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocket.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocket.h new file mode 100644 index 0000000..37df88c --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocket.h @@ -0,0 +1,180 @@ +/* + * IXWebSocket.h + * Author: Benjamin Sergeant + * Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved. + * + * WebSocket RFC + * https://tools.ietf.org/html/rfc6455 + */ + +#pragma once + +#include "IXProgressCallback.h" +#include "IXSocketTLSOptions.h" +#include "IXWebSocketCloseConstants.h" +#include "IXWebSocketErrorInfo.h" +#include "IXWebSocketHttpHeaders.h" +#include "IXWebSocketMessage.h" +#include "IXWebSocketPerMessageDeflateOptions.h" +#include "IXWebSocketSendInfo.h" +#include "IXWebSocketSendData.h" +#include "IXWebSocketTransport.h" +#include +#include +#include +#include +#include + +namespace ix +{ + // https://developer.mozilla.org/en-US/docs/Web/API/WebSocket#Ready_state_constants + enum class ReadyState + { + Connecting = 0, + Open = 1, + Closing = 2, + Closed = 3 + }; + + using OnMessageCallback = std::function; + + using OnTrafficTrackerCallback = std::function; + + class WebSocket + { + public: + WebSocket(); + ~WebSocket(); + + void setUrl(const std::string& url); + + // send extra headers in client handshake request + void setExtraHeaders(const WebSocketHttpHeaders& headers); + void setPerMessageDeflateOptions( + const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions); + void setTLSOptions(const SocketTLSOptions& socketTLSOptions); + void setPingInterval(int pingIntervalSecs); + void enablePong(); + void disablePong(); + void enablePerMessageDeflate(); + void disablePerMessageDeflate(); + void addSubProtocol(const std::string& subProtocol); + void setHandshakeTimeout(int handshakeTimeoutSecs); + + // Run asynchronously, by calling start and stop. + void start(); + + // stop is synchronous + void stop(uint16_t code = WebSocketCloseConstants::kNormalClosureCode, + const std::string& reason = WebSocketCloseConstants::kNormalClosureMessage); + + // Run in blocking mode, by connecting first manually, and then calling run. + WebSocketInitResult connect(int timeoutSecs); + void run(); + + // send is in text mode by default + WebSocketSendInfo send(const std::string& data, + bool binary = false, + const OnProgressCallback& onProgressCallback = nullptr); + WebSocketSendInfo sendBinary(const std::string& data, + const OnProgressCallback& onProgressCallback = nullptr); + WebSocketSendInfo sendBinary(const IXWebSocketSendData& data, + const OnProgressCallback& onProgressCallback = nullptr); + // does not check for valid UTF-8 characters. Caller must check that. + WebSocketSendInfo sendUtf8Text(const std::string& text, + const OnProgressCallback& onProgressCallback = nullptr); + // does not check for valid UTF-8 characters. Caller must check that. + WebSocketSendInfo sendUtf8Text(const IXWebSocketSendData& text, + const OnProgressCallback& onProgressCallback = nullptr); + WebSocketSendInfo sendText(const std::string& text, + const OnProgressCallback& onProgressCallback = nullptr); + WebSocketSendInfo ping(const std::string& text); + + void close(uint16_t code = WebSocketCloseConstants::kNormalClosureCode, + const std::string& reason = WebSocketCloseConstants::kNormalClosureMessage); + + void setOnMessageCallback(const OnMessageCallback& callback); + bool isOnMessageCallbackRegistered() const; + static void setTrafficTrackerCallback(const OnTrafficTrackerCallback& callback); + static void resetTrafficTrackerCallback(); + + ReadyState getReadyState() const; + static std::string readyStateToString(ReadyState readyState); + + const std::string getUrl() const; + const WebSocketPerMessageDeflateOptions getPerMessageDeflateOptions() const; + int getPingInterval() const; + size_t bufferedAmount() const; + + void enableAutomaticReconnection(); + void disableAutomaticReconnection(); + bool isAutomaticReconnectionEnabled() const; + void setMaxWaitBetweenReconnectionRetries(uint32_t maxWaitBetweenReconnectionRetries); + void setMinWaitBetweenReconnectionRetries(uint32_t minWaitBetweenReconnectionRetries); + uint32_t getMaxWaitBetweenReconnectionRetries() const; + uint32_t getMinWaitBetweenReconnectionRetries() const; + const std::vector& getSubProtocols(); + + private: + WebSocketSendInfo sendMessage(const IXWebSocketSendData& message, + SendMessageKind sendMessageKind, + const OnProgressCallback& callback = nullptr); + + bool isConnected() const; + bool isClosing() const; + void checkConnection(bool firstConnectionAttempt); + static void invokeTrafficTrackerCallback(size_t size, bool incoming); + + // Server + WebSocketInitResult connectToSocket(std::unique_ptr, + int timeoutSecs, + bool enablePerMessageDeflate); + + WebSocketTransport _ws; + + std::string _url; + WebSocketHttpHeaders _extraHeaders; + + WebSocketPerMessageDeflateOptions _perMessageDeflateOptions; + + SocketTLSOptions _socketTLSOptions; + + mutable std::mutex _configMutex; // protect all config variables access + + OnMessageCallback _onMessageCallback; + static OnTrafficTrackerCallback _onTrafficTrackerCallback; + + std::atomic _stop; + std::thread _thread; + std::mutex _writeMutex; + + // Automatic reconnection + std::atomic _automaticReconnection; + static const uint32_t kDefaultMaxWaitBetweenReconnectionRetries; + static const uint32_t kDefaultMinWaitBetweenReconnectionRetries; + uint32_t _maxWaitBetweenReconnectionRetries; + uint32_t _minWaitBetweenReconnectionRetries; + + // Make the sleeping in the automatic reconnection cancellable + std::mutex _sleepMutex; + std::condition_variable _sleepCondition; + + std::atomic _handshakeTimeoutSecs; + static const int kDefaultHandShakeTimeoutSecs; + + // enable or disable PONG frame response to received PING frame + bool _enablePong; + static const bool kDefaultEnablePong; + + // Optional ping and pong timeout + int _pingIntervalSecs; + int _pingTimeoutSecs; + static const int kDefaultPingIntervalSecs; + static const int kDefaultPingTimeoutSecs; + + // Subprotocols + std::vector _subProtocols; + + friend class WebSocketServer; + }; +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketCloseConstants.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketCloseConstants.h new file mode 100644 index 0000000..145777b --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketCloseConstants.h @@ -0,0 +1,37 @@ +/* + * IXWebSocketCloseConstants.h + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include +#include + +namespace ix +{ + struct WebSocketCloseConstants + { + static const uint16_t kNormalClosureCode; + static const uint16_t kInternalErrorCode; + static const uint16_t kAbnormalCloseCode; + static const uint16_t kProtocolErrorCode; + static const uint16_t kNoStatusCodeErrorCode; + static const uint16_t kInvalidFramePayloadData; + + static const std::string kNormalClosureMessage; + static const std::string kInternalErrorMessage; + static const std::string kAbnormalCloseMessage; + static const std::string kPingTimeoutMessage; + static const std::string kProtocolErrorMessage; + static const std::string kNoStatusCodeErrorMessage; + static const std::string kProtocolErrorReservedBitUsed; + static const std::string kProtocolErrorPingPayloadOversized; + static const std::string kProtocolErrorCodeControlMessageFragmented; + static const std::string kProtocolErrorCodeDataOpcodeOutOfSequence; + static const std::string kProtocolErrorCodeContinuationOpCodeOutOfSequence; + static const std::string kInvalidFramePayloadDataMessage; + static const std::string kInvalidCloseCodeMessage; + }; +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketCloseInfo.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketCloseInfo.h new file mode 100644 index 0000000..409e74f --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketCloseInfo.h @@ -0,0 +1,28 @@ +/* + * IXWebSocketCloseInfo.h + * Author: Benjamin Sergeant + * Copyright (c) 2017-2019 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include +#include + +namespace ix +{ + struct WebSocketCloseInfo + { + uint16_t code; + std::string reason; + bool remote; + + WebSocketCloseInfo(uint16_t c = 0, const std::string& r = std::string(), bool rem = false) + : code(c) + , reason(r) + , remote(rem) + { + ; + } + }; +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketErrorInfo.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketErrorInfo.h new file mode 100644 index 0000000..16f3215 --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketErrorInfo.h @@ -0,0 +1,22 @@ +/* + * IXWebSocketErrorInfo.h + * Author: Benjamin Sergeant + * Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include +#include + +namespace ix +{ + struct WebSocketErrorInfo + { + uint32_t retries = 0; + double wait_time = 0; + int http_status = 0; + std::string reason; + bool decompressionError = false; + }; +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketHandshake.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketHandshake.h new file mode 100644 index 0000000..0a275e4 --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketHandshake.h @@ -0,0 +1,54 @@ +/* + * IXWebSocketHandshake.h + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include "IXCancellationRequest.h" +#include "IXSocket.h" +#include "IXWebSocketHttpHeaders.h" +#include "IXWebSocketInitResult.h" +#include "IXWebSocketPerMessageDeflate.h" +#include "IXWebSocketPerMessageDeflateOptions.h" +#include +#include +#include +#include + +namespace ix +{ + class WebSocketHandshake + { + public: + WebSocketHandshake(std::atomic& requestInitCancellation, + std::unique_ptr& _socket, + WebSocketPerMessageDeflatePtr& perMessageDeflate, + WebSocketPerMessageDeflateOptions& perMessageDeflateOptions, + std::atomic& enablePerMessageDeflate); + + WebSocketInitResult clientHandshake(const std::string& url, + const WebSocketHttpHeaders& extraHeaders, + const std::string& host, + const std::string& path, + int port, + int timeoutSecs); + + WebSocketInitResult serverHandshake(int timeoutSecs, bool enablePerMessageDeflate); + + private: + std::string genRandomString(const int len); + + // Parse HTTP headers + WebSocketInitResult sendErrorResponse(int code, const std::string& reason); + + bool insensitiveStringCompare(const std::string& a, const std::string& b); + + std::atomic& _requestInitCancellation; + std::unique_ptr& _socket; + WebSocketPerMessageDeflatePtr& _perMessageDeflate; + WebSocketPerMessageDeflateOptions& _perMessageDeflateOptions; + std::atomic& _enablePerMessageDeflate; + }; +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketHandshakeKeyGen.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketHandshakeKeyGen.h new file mode 100644 index 0000000..56528fc --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketHandshakeKeyGen.h @@ -0,0 +1,171 @@ +// Copyright (c) 2016 Alex Hultman and contributors + +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. + +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: + +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgement in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +#pragma once + +#include +#include +#include +#include + +class WebSocketHandshakeKeyGen +{ + template + struct static_for + { + void operator()(uint32_t* a, uint32_t* b) + { + static_for()(a, b); + T::template f(a, b); + } + }; + + template + struct static_for<0, T> + { + void operator()(uint32_t* /*a*/, uint32_t* /*hash*/) + { + } + }; + + template + struct Sha1Loop + { + static inline uint32_t rol(uint32_t value, size_t bits) + { + return (value << bits) | (value >> (32 - bits)); + } + static inline uint32_t blk(uint32_t b[16], size_t i) + { + return rol(b[(i + 13) & 15] ^ b[(i + 8) & 15] ^ b[(i + 2) & 15] ^ b[i], 1); + } + + template + static inline void f(uint32_t* a, uint32_t* b) + { + switch (state) + { + case 1: + a[i % 5] += + ((a[(3 + i) % 5] & (a[(2 + i) % 5] ^ a[(1 + i) % 5])) ^ a[(1 + i) % 5]) + + b[i] + 0x5a827999 + rol(a[(4 + i) % 5], 5); + a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30); + break; + case 2: + b[i] = blk(b, i); + a[(1 + i) % 5] += + ((a[(4 + i) % 5] & (a[(3 + i) % 5] ^ a[(2 + i) % 5])) ^ a[(2 + i) % 5]) + + b[i] + 0x5a827999 + rol(a[(5 + i) % 5], 5); + a[(4 + i) % 5] = rol(a[(4 + i) % 5], 30); + break; + case 3: + b[(i + 4) % 16] = blk(b, (i + 4) % 16); + a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + + b[(i + 4) % 16] + 0x6ed9eba1 + rol(a[(4 + i) % 5], 5); + a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30); + break; + case 4: + b[(i + 8) % 16] = blk(b, (i + 8) % 16); + a[i % 5] += (((a[(3 + i) % 5] | a[(2 + i) % 5]) & a[(1 + i) % 5]) | + (a[(3 + i) % 5] & a[(2 + i) % 5])) + + b[(i + 8) % 16] + 0x8f1bbcdc + rol(a[(4 + i) % 5], 5); + a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30); + break; + case 5: + b[(i + 12) % 16] = blk(b, (i + 12) % 16); + a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + + b[(i + 12) % 16] + 0xca62c1d6 + rol(a[(4 + i) % 5], 5); + a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30); + break; + case 6: b[i] += a[4 - i]; + } + } + }; + + static inline void sha1(uint32_t hash[5], uint32_t b[16]) + { + uint32_t a[5] = {hash[4], hash[3], hash[2], hash[1], hash[0]}; + static_for<16, Sha1Loop<1>>()(a, b); + static_for<4, Sha1Loop<2>>()(a, b); + static_for<20, Sha1Loop<3>>()(a, b); + static_for<20, Sha1Loop<4>>()(a, b); + static_for<20, Sha1Loop<5>>()(a, b); + static_for<5, Sha1Loop<6>>()(a, hash); + } + + static inline void base64(unsigned char* src, char* dst) + { + const char* b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + for (int i = 0; i < 18; i += 3) + { + *dst++ = b64[(src[i] >> 2) & 63]; + *dst++ = b64[((src[i] & 3) << 4) | ((src[i + 1] & 240) >> 4)]; + *dst++ = b64[((src[i + 1] & 15) << 2) | ((src[i + 2] & 192) >> 6)]; + *dst++ = b64[src[i + 2] & 63]; + } + *dst++ = b64[(src[18] >> 2) & 63]; + *dst++ = b64[((src[18] & 3) << 4) | ((src[19] & 240) >> 4)]; + *dst++ = b64[((src[19] & 15) << 2)]; + *dst++ = '='; + } + +public: + static inline void generate(const std::string& inputStr, char output[28]) + { + char input[25] = {}; + strncpy(input, inputStr.c_str(), 25 - 1); + input[25 - 1] = '\0'; + + uint32_t b_output[5] = {0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0}; + uint32_t b_input[16] = {0, + 0, + 0, + 0, + 0, + 0, + 0x32353845, + 0x41464135, + 0x2d453931, + 0x342d3437, + 0x44412d39, + 0x3543412d, + 0x43354142, + 0x30444338, + 0x35423131, + 0x80000000}; + + for (int i = 0; i < 6; i++) + { + b_input[i] = (input[4 * i + 3] & 0xff) | (input[4 * i + 2] & 0xff) << 8 | + (input[4 * i + 1] & 0xff) << 16 | (input[4 * i + 0] & 0xff) << 24; + } + sha1(b_output, b_input); + uint32_t last_b[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 480}; + sha1(b_output, last_b); + for (int i = 0; i < 5; i++) + { + uint32_t tmp = b_output[i]; + char* bytes = (char*) &b_output[i]; + bytes[3] = tmp & 0xff; + bytes[2] = (tmp >> 8) & 0xff; + bytes[1] = (tmp >> 16) & 0xff; + bytes[0] = (tmp >> 24) & 0xff; + } + base64((unsigned char*) b_output, output); + } +}; diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketHttpHeaders.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketHttpHeaders.h new file mode 100644 index 0000000..7ba8c4e --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketHttpHeaders.h @@ -0,0 +1,23 @@ +/* + * IXWebSocketHttpHeaders.h + * Author: Benjamin Sergeant + * Copyright (c) 2018 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include "IXCancellationRequest.h" +#include "IXStrCaseCompare.h" +#include +#include +#include + +namespace ix +{ + class Socket; + + using WebSocketHttpHeaders = std::map; + + std::pair parseHttpHeaders( + std::unique_ptr& socket, const CancellationRequest& isCancellationRequested); +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketInitResult.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketInitResult.h new file mode 100644 index 0000000..d60e4f8 --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketInitResult.h @@ -0,0 +1,36 @@ +/* + * IXWebSocketInitResult.h + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include "IXWebSocketHttpHeaders.h" + +namespace ix +{ + struct WebSocketInitResult + { + bool success; + int http_status; + std::string errorStr; + WebSocketHttpHeaders headers; + std::string uri; + std::string protocol; + + WebSocketInitResult(bool s = false, + int status = 0, + const std::string& e = std::string(), + WebSocketHttpHeaders h = WebSocketHttpHeaders(), + const std::string& u = std::string()) + { + success = s; + http_status = status; + errorStr = e; + headers = h; + uri = u; + protocol = h["Sec-WebSocket-Protocol"]; + } + }; +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketMessage.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketMessage.h new file mode 100644 index 0000000..25a00ce --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketMessage.h @@ -0,0 +1,60 @@ +/* + * IXWebSocketMessage.h + * Author: Benjamin Sergeant + * Copyright (c) 2017-2019 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include "IXWebSocketCloseInfo.h" +#include "IXWebSocketErrorInfo.h" +#include "IXWebSocketMessageType.h" +#include "IXWebSocketOpenInfo.h" +#include +#include + +namespace ix +{ + struct WebSocketMessage + { + WebSocketMessageType type; + const std::string& str; + size_t wireSize; + WebSocketErrorInfo errorInfo; + WebSocketOpenInfo openInfo; + WebSocketCloseInfo closeInfo; + bool binary; + + WebSocketMessage(WebSocketMessageType t, + const std::string& s, + size_t w, + WebSocketErrorInfo e, + WebSocketOpenInfo o, + WebSocketCloseInfo c, + bool b = false) + : type(t) + , str(s) + , wireSize(w) + , errorInfo(e) + , openInfo(o) + , closeInfo(c) + , binary(b) + { + ; + } + + /** + * @brief Deleted overload to prevent binding `str` to a temporary, which would cause + * undefined behavior since class members don't extend lifetime beyond the constructor call. + */ + WebSocketMessage(WebSocketMessageType t, + std::string&& s, + size_t w, + WebSocketErrorInfo e, + WebSocketOpenInfo o, + WebSocketCloseInfo c, + bool b = false) = delete; + }; + + using WebSocketMessagePtr = std::unique_ptr; +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketMessageType.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketMessageType.h new file mode 100644 index 0000000..c7ee45d --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketMessageType.h @@ -0,0 +1,21 @@ +/* + * IXWebSocketMessageType.h + * Author: Benjamin Sergeant + * Copyright (c) 2017-2019 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +namespace ix +{ + enum class WebSocketMessageType + { + Message = 0, + Open = 1, + Close = 2, + Error = 3, + Ping = 4, + Pong = 5, + Fragment = 6 + }; +} diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketOpenInfo.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketOpenInfo.h new file mode 100644 index 0000000..3eb32b0 --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketOpenInfo.h @@ -0,0 +1,31 @@ +/* + * IXWebSocketOpenInfo.h + * Author: Benjamin Sergeant + * Copyright (c) 2017-2019 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include "IXWebSocketHttpHeaders.h" +#include +#include + +namespace ix +{ + struct WebSocketOpenInfo + { + std::string uri; + WebSocketHttpHeaders headers; + std::string protocol; + + WebSocketOpenInfo(const std::string& u = std::string(), + const WebSocketHttpHeaders& h = WebSocketHttpHeaders(), + const std::string& p = std::string()) + : uri(u) + , headers(h) + , protocol(p) + { + ; + } + }; +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketPerMessageDeflate.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketPerMessageDeflate.h new file mode 100644 index 0000000..5d4cc38 --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketPerMessageDeflate.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2015, Peter Thorson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the WebSocket++ Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Author: Benjamin Sergeant + * Copyright (c) 2018 Machine Zone, Inc. All rights reserved. + * + * Adapted from websocketpp/extensions/permessage_deflate/enabled.hpp + * (same license as MZ: https://opensource.org/licenses/BSD-3-Clause) + */ + +#pragma once + +#include +#include +#include "IXWebSocketSendData.h" + +namespace ix +{ + class WebSocketPerMessageDeflateOptions; + class WebSocketPerMessageDeflateCompressor; + class WebSocketPerMessageDeflateDecompressor; + + class WebSocketPerMessageDeflate + { + public: + WebSocketPerMessageDeflate(); + ~WebSocketPerMessageDeflate(); + + bool init(const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions); + bool compress(const IXWebSocketSendData& in, std::string& out); + bool compress(const std::string& in, std::string& out); + bool decompress(const std::string& in, std::string& out); + + private: + std::unique_ptr _compressor; + std::unique_ptr _decompressor; + }; + + using WebSocketPerMessageDeflatePtr = std::unique_ptr; +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketPerMessageDeflateCodec.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketPerMessageDeflateCodec.h new file mode 100644 index 0000000..8c0d6b1 --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketPerMessageDeflateCodec.h @@ -0,0 +1,64 @@ +/* + * IXWebSocketPerMessageDeflateCodec.h + * Author: Benjamin Sergeant + * Copyright (c) 2018-2019 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#ifdef IXWEBSOCKET_USE_ZLIB +#include "zlib.h" +#endif +#include +#include +#include +#include "IXWebSocketSendData.h" + +namespace ix +{ + class WebSocketPerMessageDeflateCompressor + { + public: + WebSocketPerMessageDeflateCompressor(); + ~WebSocketPerMessageDeflateCompressor(); + + bool init(uint8_t deflateBits, bool clientNoContextTakeOver); + bool compress(const IXWebSocketSendData& in, std::string& out); + bool compress(const std::string& in, std::string& out); + bool compress(const std::string& in, std::vector& out); + bool compress(const std::vector& in, std::string& out); + bool compress(const std::vector& in, std::vector& out); + + private: + template + bool compressData(const T& in, S& out); + template + bool endsWithEmptyUnCompressedBlock(const T& value); + + int _flush; + std::array _compressBuffer; + +#ifdef IXWEBSOCKET_USE_ZLIB + z_stream _deflateState; +#endif + }; + + class WebSocketPerMessageDeflateDecompressor + { + public: + WebSocketPerMessageDeflateDecompressor(); + ~WebSocketPerMessageDeflateDecompressor(); + + bool init(uint8_t inflateBits, bool clientNoContextTakeOver); + bool decompress(const std::string& in, std::string& out); + + private: + int _flush; + std::array _compressBuffer; + +#ifdef IXWEBSOCKET_USE_ZLIB + z_stream _inflateState; +#endif + }; + +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketPerMessageDeflateOptions.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketPerMessageDeflateOptions.h new file mode 100644 index 0000000..7cd33c0 --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketPerMessageDeflateOptions.h @@ -0,0 +1,47 @@ +/* + * IXWebSocketPerMessageDeflateOptions.h + * Author: Benjamin Sergeant + * Copyright (c) 2018 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include + +namespace ix +{ + class WebSocketPerMessageDeflateOptions + { + public: + WebSocketPerMessageDeflateOptions( + bool enabled = false, + bool clientNoContextTakeover = false, + bool serverNoContextTakeover = false, + uint8_t clientMaxWindowBits = kDefaultClientMaxWindowBits, + uint8_t serverMaxWindowBits = kDefaultServerMaxWindowBits); + + WebSocketPerMessageDeflateOptions(std::string extension); + + std::string generateHeader(); + bool enabled() const; + bool getClientNoContextTakeover() const; + bool getServerNoContextTakeover() const; + uint8_t getServerMaxWindowBits() const; + uint8_t getClientMaxWindowBits() const; + + static bool startsWith(const std::string& str, const std::string& start); + static std::string removeSpaces(const std::string& str); + + static uint8_t const kDefaultClientMaxWindowBits; + static uint8_t const kDefaultServerMaxWindowBits; + + private: + bool _enabled; + bool _clientNoContextTakeover; + bool _serverNoContextTakeover; + uint8_t _clientMaxWindowBits; + uint8_t _serverMaxWindowBits; + + void sanitizeClientMaxWindowBits(); + }; +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketProxyServer.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketProxyServer.h new file mode 100644 index 0000000..7a55e47 --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketProxyServer.h @@ -0,0 +1,24 @@ +/* + * IXWebSocketProxyServer.h + * Author: Benjamin Sergeant + * Copyright (c) 2019-2020 Machine Zone, Inc. All rights reserved. + */ +#pragma once + +#include "IXSocketTLSOptions.h" +#include +#include +#include +#include + +namespace ix +{ + using RemoteUrlsMapping = std::map; + + int websocket_proxy_server_main(int port, + const std::string& hostname, + const ix::SocketTLSOptions& tlsOptions, + const std::string& remoteUrl, + const RemoteUrlsMapping& remoteUrlsMapping, + bool verbose); +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketSendData.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketSendData.h new file mode 100644 index 0000000..86031aa --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketSendData.h @@ -0,0 +1,128 @@ +/* + * IXWebSocketSendData.h + * + * WebSocket (Binary/Text) send data buffer + */ + +#pragma once + +#include +#include +#include + +namespace ix +{ + /* + * IXWebSocketSendData implements a wrapper for std::string, std:vector and char*. + * It removes the necessarity to copy the data or string into a std::string + */ + class IXWebSocketSendData { + public: + + template + struct IXWebSocketSendData_const_iterator + //: public std::iterator + { + typedef IXWebSocketSendData_const_iterator const_iterator; + + using iterator_category = std::forward_iterator_tag; + using difference_type = std::ptrdiff_t; + using value_type = T; + using pointer = value_type*; + using reference = const value_type&; + + pointer _ptr; + public: + IXWebSocketSendData_const_iterator() : _ptr(nullptr) {} + IXWebSocketSendData_const_iterator(pointer ptr) : _ptr(ptr) {} + ~IXWebSocketSendData_const_iterator() {} + + const_iterator operator++(int) { return const_iterator(_ptr++); } + const_iterator& operator++() { ++_ptr; return *this; } + reference operator* () const { return *_ptr; } + pointer operator->() const { return _ptr; } + const_iterator operator+ (const difference_type offset) const { return const_iterator(_ptr + offset); } + const_iterator operator- (const difference_type offset) const { return const_iterator(_ptr - offset); } + difference_type operator- (const const_iterator& rhs) const { return _ptr - rhs._ptr; } + bool operator==(const const_iterator& rhs) const { return _ptr == rhs._ptr; } + bool operator!=(const const_iterator& rhs) const { return _ptr != rhs._ptr; } + const_iterator& operator+=(const difference_type offset) { _ptr += offset; return *this; } + const_iterator& operator-=(const difference_type offset) { _ptr -= offset; return *this; } + }; + + using const_iterator = IXWebSocketSendData_const_iterator; + + /* The assigned std::string must be kept alive for the lifetime of the input buffer */ + IXWebSocketSendData(const std::string& str) + : _data(str.data()) + , _size(str.size()) + { + } + + /* The assigned std::vector must be kept alive for the lifetime of the input buffer */ + IXWebSocketSendData(const std::vector& v) + : _data(v.data()) + , _size(v.size()) + { + } + + /* The assigned std::vector must be kept alive for the lifetime of the input buffer */ + IXWebSocketSendData(const std::vector& v) + : _data(reinterpret_cast(v.data())) + , _size(v.size()) + { + } + + /* The assigned memory must be kept alive for the lifetime of the input buffer */ + IXWebSocketSendData(const char* data, size_t size) + : _data(data) + , _size(data == nullptr ? 0 : size) + { + } + + bool empty() const + { + return _data == nullptr || _size == 0; + } + + const char* c_str() const + { + return _data; + } + + const char* data() const + { + return _data; + } + + size_t size() const + { + return _size; + } + + inline const_iterator begin() const + { + return const_iterator(const_cast(_data)); + } + + inline const_iterator end() const + { + return const_iterator(const_cast(_data) + _size); + } + + inline const_iterator cbegin() const + { + return begin(); + } + + inline const_iterator cend() const + { + return end(); + } + + private: + const char* _data; + const size_t _size; + }; + +} \ No newline at end of file diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketSendInfo.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketSendInfo.h new file mode 100644 index 0000000..c66d4a6 --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketSendInfo.h @@ -0,0 +1,27 @@ +/* + * IXWebSocketSendInfo.h + * Author: Benjamin Sergeant + * Copyright (c) 2018 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +namespace ix +{ + struct WebSocketSendInfo + { + bool success; + bool compressionError; + size_t payloadSize; + size_t wireSize; + + WebSocketSendInfo(bool s = false, bool c = false, size_t p = 0, size_t w = 0) + : success(s) + , compressionError(c) + , payloadSize(p) + , wireSize(w) + { + ; + } + }; +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketServer.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketServer.h new file mode 100644 index 0000000..6cae633 --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketServer.h @@ -0,0 +1,77 @@ +/* + * IXWebSocketServer.h + * Author: Benjamin Sergeant + * Copyright (c) 2018 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include "IXSocketServer.h" +#include "IXWebSocket.h" +#include +#include +#include +#include +#include +#include +#include +#include // pair + +namespace ix +{ + class WebSocketServer : public SocketServer + { + public: + using OnConnectionCallback = + std::function, std::shared_ptr)>; + + using OnClientMessageCallback = std::function, WebSocket&, const WebSocketMessagePtr&)>; + + WebSocketServer(int port = SocketServer::kDefaultPort, + const std::string& host = SocketServer::kDefaultHost, + int backlog = SocketServer::kDefaultTcpBacklog, + size_t maxConnections = SocketServer::kDefaultMaxConnections, + int handshakeTimeoutSecs = WebSocketServer::kDefaultHandShakeTimeoutSecs, + int addressFamily = SocketServer::kDefaultAddressFamily); + virtual ~WebSocketServer(); + virtual void stop() final; + + void enablePong(); + void disablePong(); + void disablePerMessageDeflate(); + + void setOnConnectionCallback(const OnConnectionCallback& callback); + void setOnClientMessageCallback(const OnClientMessageCallback& callback); + + // Get all the connected clients + std::set> getClients(); + + void makeBroadcastServer(); + bool listenAndStart(); + + const static int kDefaultHandShakeTimeoutSecs; + + int getHandshakeTimeoutSecs(); + bool isPongEnabled(); + bool isPerMessageDeflateEnabled(); + private: + // Member variables + int _handshakeTimeoutSecs; + bool _enablePong; + bool _enablePerMessageDeflate; + + OnConnectionCallback _onConnectionCallback; + OnClientMessageCallback _onClientMessageCallback; + + std::mutex _clientsMutex; + std::set> _clients; + + const static bool kDefaultEnablePong; + + // Methods + virtual void handleConnection(std::unique_ptr socket, + std::shared_ptr connectionState); + virtual size_t getConnectedClientsCount() final; + }; +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketTransport.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketTransport.h new file mode 100644 index 0000000..bdfd409 --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketTransport.h @@ -0,0 +1,276 @@ +/* + * IXWebSocketTransport.h + * Author: Benjamin Sergeant + * Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +// +// Adapted from https://github.com/dhbaird/easywsclient +// + +#include "IXCancellationRequest.h" +#include "IXProgressCallback.h" +#include "IXSocketTLSOptions.h" +#include "IXWebSocketCloseConstants.h" +#include "IXWebSocketHandshake.h" +#include "IXWebSocketHttpHeaders.h" +#include "IXWebSocketPerMessageDeflate.h" +#include "IXWebSocketPerMessageDeflateOptions.h" +#include "IXWebSocketSendInfo.h" +#include "IXWebSocketSendData.h" +#include +#include +#include +#include +#include +#include +#include + +namespace ix +{ + class Socket; + + enum class SendMessageKind + { + Text, + Binary, + Ping + }; + + class WebSocketTransport + { + public: + enum class ReadyState + { + CLOSING, + CLOSED, + CONNECTING, + OPEN + }; + + enum class MessageKind + { + MSG_TEXT, + MSG_BINARY, + PING, + PONG, + FRAGMENT + }; + + enum class PollResult + { + Succeeded, + AbnormalClose, + CannotFlushSendBuffer + }; + + using OnMessageCallback = + std::function; + using OnCloseCallback = std::function; + + WebSocketTransport(); + ~WebSocketTransport(); + + void configure(const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions, + const SocketTLSOptions& socketTLSOptions, + bool enablePong, + int pingIntervalSecs); + + // Client + WebSocketInitResult connectToUrl(const std::string& url, + const WebSocketHttpHeaders& headers, + int timeoutSecs); + + // Server + WebSocketInitResult connectToSocket(std::unique_ptr socket, + int timeoutSecs, + bool enablePerMessageDeflate); + + PollResult poll(); + WebSocketSendInfo sendBinary(const IXWebSocketSendData& message, + const OnProgressCallback& onProgressCallback); + WebSocketSendInfo sendText(const IXWebSocketSendData& message, + const OnProgressCallback& onProgressCallback); + WebSocketSendInfo sendPing(const IXWebSocketSendData& message); + + void close(uint16_t code = WebSocketCloseConstants::kNormalClosureCode, + const std::string& reason = WebSocketCloseConstants::kNormalClosureMessage, + size_t closeWireSize = 0, + bool remote = false); + + void closeSocket(); + + ReadyState getReadyState() const; + void setReadyState(ReadyState readyState); + void setOnCloseCallback(const OnCloseCallback& onCloseCallback); + void dispatch(PollResult pollResult, const OnMessageCallback& onMessageCallback); + size_t bufferedAmount() const; + + // internal + WebSocketSendInfo sendHeartBeat(); + + private: + std::string _url; + + struct wsheader_type + { + unsigned header_size; + bool fin; + bool rsv1; + bool rsv2; + bool rsv3; + bool mask; + enum opcode_type + { + CONTINUATION = 0x0, + TEXT_FRAME = 0x1, + BINARY_FRAME = 0x2, + CLOSE = 8, + PING = 9, + PONG = 0xa, + } opcode; + int N0; + uint64_t N; + uint8_t masking_key[4]; + }; + + // Tells whether we should mask the data we send. + // client should mask but server should not + std::atomic _useMask; + + // Tells whether we should flush the send buffer before + // saying that a send is complete. This is the mode for server code. + std::atomic _blockingSend; + + // Buffer for reading from our socket. That buffer is never resized. + std::vector _readbuf; + + // Contains all messages that were fetched in the last socket read. + // This could be a mix of control messages (Close, Ping, etc...) and + // data messages. That buffer is resized + std::vector _rxbuf; + + // Contains all messages that are waiting to be sent + std::vector _txbuf; + mutable std::mutex _txbufMutex; + + // Hold fragments for multi-fragments messages in a list. We support receiving very large + // messages (tested messages up to 700M) and we cannot put them in a single + // buffer that is resized, as this operation can be slow when a buffer has its + // size increased 2 fold, while appending to a list has a fixed cost. + std::list _chunks; + + // Record the message kind (will be TEXT or BINARY) for a fragmented + // message, present in the first chunk, since the final chunk will be a + // CONTINUATION opcode and doesn't tell the full message kind + MessageKind _fragmentedMessageKind; + + // Ditto for whether a message is compressed + bool _receivedMessageCompressed; + + // Fragments are 32K long + static constexpr size_t kChunkSize = 1 << 15; + + // Underlying TCP socket + std::unique_ptr _socket; + std::mutex _socketMutex; + + // Hold the state of the connection (OPEN, CLOSED, etc...) + std::atomic _readyState; + + OnCloseCallback _onCloseCallback; + std::string _closeReason; + mutable std::mutex _closeReasonMutex; + std::atomic _closeCode; + std::atomic _closeWireSize; + std::atomic _closeRemote; + + // Data used for Per Message Deflate compression (with zlib) + WebSocketPerMessageDeflatePtr _perMessageDeflate; + WebSocketPerMessageDeflateOptions _perMessageDeflateOptions; + std::atomic _enablePerMessageDeflate; + + std::string _decompressedMessage; + std::string _compressedMessage; + + // Used to control TLS connection behavior + SocketTLSOptions _socketTLSOptions; + + // Used to cancel dns lookup + socket connect + http upgrade + std::atomic _requestInitCancellation; + + mutable std::mutex _closingTimePointMutex; + std::chrono::time_point _closingTimePoint; + static const int kClosingMaximumWaitingDelayInMs; + + // enable auto response to ping + std::atomic _enablePong; + static const bool kDefaultEnablePong; + + // Optional ping and pong timeout + int _pingIntervalSecs; + std::atomic _pongReceived; + + static const int kDefaultPingIntervalSecs; + static const std::string kPingMessage; + std::atomic _pingCount; + + // We record when ping are being sent so that we can know when to send the next one + mutable std::mutex _lastSendPingTimePointMutex; + std::chrono::time_point _lastSendPingTimePoint; + + // If this function returns true, it is time to send a new ping + bool pingIntervalExceeded(); + void initTimePointsAfterConnect(); + + // after calling close(), if no CLOSE frame answer is received back from the remote, we + // should close the connexion + bool closingDelayExceeded(); + + void sendCloseFrame(uint16_t code, const std::string& reason); + + void closeSocketAndSwitchToClosedState(uint16_t code, + const std::string& reason, + size_t closeWireSize, + bool remote); + + bool wakeUpFromPoll(uint64_t wakeUpCode); + + bool flushSendBuffer(); + bool sendOnSocket(); + bool receiveFromSocket(); + + WebSocketSendInfo sendData(wsheader_type::opcode_type type, + const IXWebSocketSendData& message, + bool compress, + const OnProgressCallback& onProgressCallback = nullptr); + + template + bool sendFragment( + wsheader_type::opcode_type type, bool fin, Iterator begin, Iterator end, bool compress); + + void emitMessage(MessageKind messageKind, + const std::string& message, + bool compressedMessage, + const OnMessageCallback& onMessageCallback); + + bool isSendBufferEmpty() const; + + template + void appendToSendBuffer(const std::vector& header, + Iterator begin, + Iterator end, + uint64_t message_size, + uint8_t masking_key[4]); + + unsigned getRandomUnsigned(); + void unmaskReceiveBuffer(const wsheader_type& ws); + + std::string getMergedChunks() const; + + void setCloseReason(const std::string& reason); + const std::string& getCloseReason() const; + }; +} // namespace ix diff --git a/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketVersion.h b/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketVersion.h new file mode 100644 index 0000000..3618e90 --- /dev/null +++ b/appdep/libs/libixwebsocket/include/ixwebsocket/IXWebSocketVersion.h @@ -0,0 +1,9 @@ +/* + * IXWebSocketVersion.h + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#define IX_WEBSOCKET_VERSION "11.4.3" diff --git a/appdep/libs/libixwebsocket/lib/cmake/ixwebsocket/ixwebsocket-config.cmake b/appdep/libs/libixwebsocket/lib/cmake/ixwebsocket/ixwebsocket-config.cmake new file mode 100644 index 0000000..3e36c05 --- /dev/null +++ b/appdep/libs/libixwebsocket/lib/cmake/ixwebsocket/ixwebsocket-config.cmake @@ -0,0 +1,9 @@ + + +include(CMakeFindDependencyMacro) + +if (0) + find_dependency(ZLIB) +endif() + +include("${CMAKE_CURRENT_LIST_DIR}/ixwebsocket-targets.cmake") diff --git a/appdep/libs/libixwebsocket/lib/cmake/ixwebsocket/ixwebsocket-targets-noconfig.cmake b/appdep/libs/libixwebsocket/lib/cmake/ixwebsocket/ixwebsocket-targets-noconfig.cmake new file mode 100644 index 0000000..35afc67 --- /dev/null +++ b/appdep/libs/libixwebsocket/lib/cmake/ixwebsocket/ixwebsocket-targets-noconfig.cmake @@ -0,0 +1,19 @@ +#---------------------------------------------------------------- +# Generated CMake target import file. +#---------------------------------------------------------------- + +# Commands may need to know the format version. +set(CMAKE_IMPORT_FILE_VERSION 1) + +# Import target "ixwebsocket::ixwebsocket" for configuration "" +set_property(TARGET ixwebsocket::ixwebsocket APPEND PROPERTY IMPORTED_CONFIGURATIONS NOCONFIG) +set_target_properties(ixwebsocket::ixwebsocket PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES_NOCONFIG "CXX" + IMPORTED_LOCATION_NOCONFIG "${_IMPORT_PREFIX}/./ixwebsocket/lib/libixwebsocket.a" + ) + +list(APPEND _cmake_import_check_targets ixwebsocket::ixwebsocket ) +list(APPEND _cmake_import_check_files_for_ixwebsocket::ixwebsocket "${_IMPORT_PREFIX}/./ixwebsocket/lib/libixwebsocket.a" ) + +# Commands beyond this point should not need to know the version. +set(CMAKE_IMPORT_FILE_VERSION) diff --git a/appdep/libs/libixwebsocket/lib/cmake/ixwebsocket/ixwebsocket-targets.cmake b/appdep/libs/libixwebsocket/lib/cmake/ixwebsocket/ixwebsocket-targets.cmake new file mode 100644 index 0000000..9002cb5 --- /dev/null +++ b/appdep/libs/libixwebsocket/lib/cmake/ixwebsocket/ixwebsocket-targets.cmake @@ -0,0 +1,109 @@ +# Generated by CMake + +if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.8) + message(FATAL_ERROR "CMake >= 2.8.0 required") +endif() +if(CMAKE_VERSION VERSION_LESS "2.8.3") + message(FATAL_ERROR "CMake >= 2.8.3 required") +endif() +cmake_policy(PUSH) +cmake_policy(VERSION 2.8.3...3.23) +#---------------------------------------------------------------- +# Generated CMake target import file. +#---------------------------------------------------------------- + +# Commands may need to know the format version. +set(CMAKE_IMPORT_FILE_VERSION 1) + +# Protect against multiple inclusion, which would fail when already imported targets are added once more. +set(_cmake_targets_defined "") +set(_cmake_targets_not_defined "") +set(_cmake_expected_targets "") +foreach(_cmake_expected_target IN ITEMS ixwebsocket::ixwebsocket) + list(APPEND _cmake_expected_targets "${_cmake_expected_target}") + if(TARGET "${_cmake_expected_target}") + list(APPEND _cmake_targets_defined "${_cmake_expected_target}") + else() + list(APPEND _cmake_targets_not_defined "${_cmake_expected_target}") + endif() +endforeach() +unset(_cmake_expected_target) +if(_cmake_targets_defined STREQUAL _cmake_expected_targets) + unset(_cmake_targets_defined) + unset(_cmake_targets_not_defined) + unset(_cmake_expected_targets) + unset(CMAKE_IMPORT_FILE_VERSION) + cmake_policy(POP) + return() +endif() +if(NOT _cmake_targets_defined STREQUAL "") + string(REPLACE ";" ", " _cmake_targets_defined_text "${_cmake_targets_defined}") + string(REPLACE ";" ", " _cmake_targets_not_defined_text "${_cmake_targets_not_defined}") + message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_cmake_targets_defined_text}\nTargets not yet defined: ${_cmake_targets_not_defined_text}\n") +endif() +unset(_cmake_targets_defined) +unset(_cmake_targets_not_defined) +unset(_cmake_expected_targets) + + +# Compute the installation prefix relative to this file. +get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +if(_IMPORT_PREFIX STREQUAL "/") + set(_IMPORT_PREFIX "") +endif() + +# Create imported target ixwebsocket::ixwebsocket +add_library(ixwebsocket::ixwebsocket STATIC IMPORTED) + +set_target_properties(ixwebsocket::ixwebsocket PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/./ixwebsocket/include/ixwebsocket" + INTERFACE_LINK_LIBRARIES "\$" +) + +if(CMAKE_VERSION VERSION_LESS 2.8.12) + message(FATAL_ERROR "This file relies on consumers using CMake 2.8.12 or greater.") +endif() + +# Load information for each installed configuration. +file(GLOB _cmake_config_files "${CMAKE_CURRENT_LIST_DIR}/ixwebsocket-targets-*.cmake") +foreach(_cmake_config_file IN LISTS _cmake_config_files) + include("${_cmake_config_file}") +endforeach() +unset(_cmake_config_file) +unset(_cmake_config_files) + +# Cleanup temporary variables. +set(_IMPORT_PREFIX) + +# Loop over all imported files and verify that they actually exist +foreach(_cmake_target IN LISTS _cmake_import_check_targets) + foreach(_cmake_file IN LISTS "_cmake_import_check_files_for_${_cmake_target}") + if(NOT EXISTS "${_cmake_file}") + message(FATAL_ERROR "The imported target \"${_cmake_target}\" references the file + \"${_cmake_file}\" +but this file does not exist. Possible reasons include: +* The file was deleted, renamed, or moved to another location. +* An install or uninstall procedure did not complete successfully. +* The installation package was faulty and contained + \"${CMAKE_CURRENT_LIST_FILE}\" +but not all the files it references. +") + endif() + endforeach() + unset(_cmake_file) + unset("_cmake_import_check_files_for_${_cmake_target}") +endforeach() +unset(_cmake_target) +unset(_cmake_import_check_targets) + +# This file does not depend on other imported targets which have +# been exported from the same project but in a separate export set. + +# Commands beyond this point should not need to know the version. +set(CMAKE_IMPORT_FILE_VERSION) +cmake_policy(POP) diff --git a/appdep/libs/libixwebsocket/lib/libixwebsocket.a b/appdep/libs/libixwebsocket/lib/libixwebsocket.a new file mode 100644 index 0000000..0f1cb72 Binary files /dev/null and b/appdep/libs/libixwebsocket/lib/libixwebsocket.a differ diff --git a/appsrc/appbase/dep.hpp b/appsrc/appbase/dep.hpp new file mode 100644 index 0000000..0bb4fe1 --- /dev/null +++ b/appsrc/appbase/dep.hpp @@ -0,0 +1,10 @@ +#pragma once +#include "components/uart_printer/uart_printer.hpp" +#include "components/zservice_container/zservice_container.hpp" +#include "iflytop/core/core.hpp" + +// +#include "gconfig.hpp" +#include "iflytop/core/components/jobs/work_queue.hpp" +#include "iflytop/core/components/stringutils.hpp" +#include "project_setting.hpp" \ No newline at end of file diff --git a/appsrc/appbase/gconfig.hpp b/appsrc/appbase/gconfig.hpp new file mode 100644 index 0000000..65dbf11 --- /dev/null +++ b/appsrc/appbase/gconfig.hpp @@ -0,0 +1,31 @@ + +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "iflytop/core/components/config_template/config_template.hpp" + +#define ConfigELEMENT_LIST(marco) \ + marco(string /* */, deviceId, "") /*设备ID*/ \ + marco(string /* */, iflytopSubDeviceCanIFName, "can0") /*子设备Can设备名称*/ \ + marco(int32_t /* */, iflytopSubDeviceCanBitrate, 500000) /*子设备Can设备波特率*/ \ + marco(string /* */, pipettingRobotCanIFName, "can1") /*移液臂Can设备名称*/ \ + marco(int32_t /* */, pipettingRobotCanBitrate, 500000) /*移液臂Can设备波特率*/ \ + marco(float /* */, dvalueCoefficient, 2) /*数值越小,相对消毒时间越长*/ \ + marco(float /* */, disinfectantWeightCorrectionFactor, 0.8500000238418579) /**/ \ + marco(string /* */, printerUart, "/dev/ttyS5") /**/ \ + marco(bool /* */, testMode, false) /**/ + +configTemplateDEFILE_CONFIG_SERVICE2( // + GConfig, // + ConfigELEMENT_LIST, // + "./configs/config.json", {}); diff --git a/appsrc/appbase/project_setting.hpp b/appsrc/appbase/project_setting.hpp new file mode 100644 index 0000000..66d821c --- /dev/null +++ b/appsrc/appbase/project_setting.hpp @@ -0,0 +1,24 @@ +#pragma once +#define LINUX_HARDWARE_ID (0x02) + +/******************************************************************************* + * LINUX_HARDWARE_REG * + *******************************************************************************/ + +#define GPM_TO_SPEED_RADIO 41.97 + +#define REG_REBOOT_FLAG 0x0000 // 重启标识 +#define REG_DEVICE_ID 0x0001 // 重启标识 +#define REG_EXCEPTION_FLAG 0x0100 // 异常标志位 + +#define GPM_TO_SPEED(gpm) (gpm * GPM_TO_SPEED_RADIO) +#define SPEED_TO_GPM(speed) ((speed / GPM_TO_SPEED_RADIO) + 0.5) + +#define EMTPTY_LINE_WHEN_DISINFECTION 60 + +#define MAX_DISINFECTIONLOGGER_FILE_NUM 10 // 最大日志文件数量 +#define USER_BEHAVIOR_RECORD_DB_MAX_RECORDS 3000 +#define SENSOR_PREHEART_TIME_S (5 * 60) + +#define VERSION "1.0.0" +#define PROJECT_NAME "TRANSMIT_DM" \ No newline at end of file diff --git a/src/app/app_components/app_errorcode_mgr/app_errorcode_mgr.hpp b/appsrc/appcomponents/app_errorcode_mgr/app_errorcode_mgr.hpp similarity index 100% rename from src/app/app_components/app_errorcode_mgr/app_errorcode_mgr.hpp rename to appsrc/appcomponents/app_errorcode_mgr/app_errorcode_mgr.hpp diff --git a/src/app/app_components/canchannel/com/socket_can.cpp b/appsrc/appcomponents/canchannel/com/socket_can.cpp similarity index 100% rename from src/app/app_components/canchannel/com/socket_can.cpp rename to appsrc/appcomponents/canchannel/com/socket_can.cpp diff --git a/src/app/app_components/canchannel/com/socket_can.hpp b/appsrc/appcomponents/canchannel/com/socket_can.hpp similarity index 100% rename from src/app/app_components/canchannel/com/socket_can.hpp rename to appsrc/appcomponents/canchannel/com/socket_can.hpp diff --git a/src/app/app_components/canchannel/com/zscanprotocol_com.cpp b/appsrc/appcomponents/canchannel/com/zscanprotocol_com.cpp similarity index 96% rename from src/app/app_components/canchannel/com/zscanprotocol_com.cpp rename to appsrc/appcomponents/canchannel/com/zscanprotocol_com.cpp index 77bbdf6..ce377d3 100644 --- a/src/app/app_components/canchannel/com/zscanprotocol_com.cpp +++ b/appsrc/appcomponents/canchannel/com/zscanprotocol_com.cpp @@ -2,7 +2,7 @@ #include -#include "app/app_components/app_errorcode_mgr/app_errorcode_mgr.hpp" +#include "appcomponents/app_errorcode_mgr/app_errorcode_mgr.hpp" #include "app_protocols/appexception/appexception.hpp" using namespace iflytop; @@ -10,12 +10,13 @@ using namespace zscanprotocol; #define TAG "ZScanProtocolCom" + void ZSCanProtocolCom::initialize(const char *canname, int baudrate, bool enableLoopBack) { // m_channel = make_shared(); m_channel->initialize(canname, baudrate, enableLoopBack); m_channel->regFrameCB([this](shared_ptr canframe) { // - // ZLOGI(TAG, "can rx: 0x%08x %d %s", canframe->id, canframe->dlc, zhex2str(canframe->data, canframe->dlc).c_str()); + logger->debug("can rx: {} {} {}", canframe->id, canframe->dlc, StringUtils::bytesToString(canframe->data, canframe->dlc).c_str()); /** * @brief 消息格式 @@ -32,7 +33,7 @@ void ZSCanProtocolCom::initialize(const char *canname, int baudrate, bool enable uint8_t frameId = canid->frameNumAndFrameId & 0x0f; CanPacketRxBuffer *rxbuf = nullptr; - // ZLOGI(TAG, "from:%d to:%d frameNum:%d ", canid->from, canid->to, canid->frameNumAndFrameId); + logger->debug("from:{} to:{} frameNum:{} ", canid->from, canid->to, canid->frameNumAndFrameId); rxbuf = findRxBuff(from); if (!rxbuf) { @@ -49,7 +50,7 @@ void ZSCanProtocolCom::initialize(const char *canname, int baudrate, bool enable // ZLOGI(TAG, "rx packet %d %d /%d", rxbuf->rxPacketNum, frameId,nframe); if (rxbuf->rxPacketNum != frameId) { - // ZLOGE(TAG, "lost subpacket from %d", from); + logger->error("lost subpacket from {}", from); rxbuf->rxPacketNum = 0; rxbuf->rxdataSize = 0; return; diff --git a/src/app/app_components/canchannel/com/zscanprotocol_com.hpp b/appsrc/appcomponents/canchannel/com/zscanprotocol_com.hpp similarity index 100% rename from src/app/app_components/canchannel/com/zscanprotocol_com.hpp rename to appsrc/appcomponents/canchannel/com/zscanprotocol_com.hpp diff --git a/src/app/app_components/canchannel/transmit_disinfection_can_master.cpp b/appsrc/appcomponents/canchannel/transmit_disinfection_can_master.cpp similarity index 99% rename from src/app/app_components/canchannel/transmit_disinfection_can_master.cpp rename to appsrc/appcomponents/canchannel/transmit_disinfection_can_master.cpp index ceebd84..a35a484 100644 --- a/src/app/app_components/canchannel/transmit_disinfection_can_master.cpp +++ b/appsrc/appcomponents/canchannel/transmit_disinfection_can_master.cpp @@ -1,6 +1,6 @@ #include "transmit_disinfection_can_master.hpp" -#include "app/app_components/app_errorcode_mgr/app_errorcode_mgr.hpp" +#include "appcomponents/app_errorcode_mgr/app_errorcode_mgr.hpp" using namespace iflytop; using namespace zscanprotocol; using namespace transmit_disfection_protocol; diff --git a/src/app/app_components/canchannel/transmit_disinfection_can_master.hpp b/appsrc/appcomponents/canchannel/transmit_disinfection_can_master.hpp similarity index 99% rename from src/app/app_components/canchannel/transmit_disinfection_can_master.hpp rename to appsrc/appcomponents/canchannel/transmit_disinfection_can_master.hpp index 92bdce7..9e6bc40 100644 --- a/src/app/app_components/canchannel/transmit_disinfection_can_master.hpp +++ b/appsrc/appcomponents/canchannel/transmit_disinfection_can_master.hpp @@ -13,7 +13,7 @@ #include // -#include "app/app_components/canchannel/com/zscanprotocol_com.hpp" +#include "appcomponents/canchannel/com/zscanprotocol_com.hpp" #include "app_protocols/transmit_disfection_protocol/transmit_disfection_protocol.hpp" #define DEFUALT_OVERTIME 30 diff --git a/appsrc/main.cpp b/appsrc/main.cpp new file mode 100644 index 0000000..1866b41 --- /dev/null +++ b/appsrc/main.cpp @@ -0,0 +1,92 @@ + +#include +#include + +#include "appbase/dep.hpp" +#include "service/main_control_service.hpp" + +using namespace iflytop; +using namespace core; +using namespace std; + +namespace iflytop { +using namespace iflytop; +using namespace core; +using namespace std; +class Main { + ENABLE_LOGGER(Main); + + private: + unique_ptr thread; + + private: + int main(int argc, char *argv[]); + + public: + static Main *g_main; + static void _onsignal(int signo) { g_main->onsignal(signo); } + void onsignal(int signo); + + public: + Main(/* args */) {} + ~Main() {} + void run(int argc, char *argv[]); + void dosystem(string order, bool dump) { + if (dump) logger->info("{}", order); + system(order.c_str()); + } +}; + +}; // namespace iflytop + +/******************************************************************************* + * MAIN => MAIN * + *******************************************************************************/ +Main *Main::g_main; +extern "C" { +int main(int argc, char *argv[]) { + Main main; + Main::g_main = &main; + main.run(argc, argv); +} +} + +void Main::onsignal(int signo) { exit(0); } +void Main::run(int argc, char *argv[]) { + // ::signal(SIGINT, Main::_onsignal); + thread.reset(new Thread("main", [&]() { exit(main(argc, argv)); })); + while (true) sleep(1000); +} +int Main::main(int argc, char *argv[]) { + /** + * @brief 系统初始化 + */ + logger->info("system setup start."); + spdlog::flush_on(spdlog::level::debug); + logger->info("#"); + logger->info("# company:{}", "ifytop"); + logger->info("# version:{}", VERSION); + logger->info("# project:{}", PROJECT_NAME); + logger->info("#"); + logger->info("build {}.....", "Config"); + // 构造GConfig + BUILD_AND_REG_SERRVICE(GConfig); + GET_SERVICE(GConfig)->initialize(); + + BUILD_AND_REG_SERRVICE(UartPrinter); + + GET_SERVICE(UartPrinter)->initialize(GET_SERVICE(GConfig)->get_printerUart(), "9600"); + + /** + * @brief + */ + // if (!device_id.empty()) GET_SERVICE(GConfig)->set_deviceId(device_id); + + auto config = GET_SERVICE(GConfig); + + // 构造MainControlService + BUILD_AND_REG_SERRVICE(MainControlService); + GET_SERVICE(MainControlService)->initialize(); + logger->info("system setup end."); + while (true) sleep(1000); +} diff --git a/appsrc/service/iflytop_front_end_service/iflytop_front_end_service.cpp b/appsrc/service/iflytop_front_end_service/iflytop_front_end_service.cpp new file mode 100644 index 0000000..081fe91 --- /dev/null +++ b/appsrc/service/iflytop_front_end_service/iflytop_front_end_service.cpp @@ -0,0 +1,163 @@ +#include "iflytop_front_end_service.hpp" +using namespace nlohmann; +using namespace iflytop; +using namespace std; +using namespace core; +using namespace ix; + +void IflytopFrontEndService::initialize(string ip) { + logger->info("IflytopFrontEndService initialize {}:{}", ip, 19001); + logger->info("IflytopFrontEndService initialize {}:{}", ip, 19002); + + m_work_queue.reset(new WorkQueue("IflytopFrontEndService-WQ")); + m_work_queue->startWork(); + + m_server.reset(new WebSocketServer(19001, ip)); + m_server->setOnConnectionCallback([this](weak_ptr webSocket, shared_ptr connectionState) { + logger->info("Remote ip: {}", connectionState->getRemoteIp()); + auto ws = webSocket.lock(); + if (!ws) return; + ws->setOnMessageCallback([this, webSocket, connectionState](const ix::WebSocketMessagePtr& msg) { + // shared_ptr messageSPtr = make_shared(*msg); + try { + onMessageCallback(webSocket, connectionState, msg); + } catch (const std::exception& e) { + logger->error("catch exception,onMessageCallback error: {}", e.what()); + } + }); + }); + + m_report_server.reset(new WebSocketServer(19002, ip)); + m_report_server->setOnConnectionCallback([this](weak_ptr webSocket, shared_ptr connectionState) { + logger->info("Remote ip: {}", connectionState->getRemoteIp()); + auto ws = webSocket.lock(); + if (!ws) return; + ws->setOnMessageCallback([this, webSocket, connectionState](const ix::WebSocketMessagePtr& msg) {}); + }); + + + m_initialized = true; +} +void IflytopFrontEndService::startListen() { + if (!m_server->listen().first) { + logger->error("listen error!!!!"); + return; + } + + if (!m_report_server->listen().first) { + logger->error("listen error!!!!"); + return; + } + + m_server->disablePerMessageDeflate(); + m_server->start(); + // m_server->wait(); + + m_report_server->disablePerMessageDeflate(); + m_report_server->start(); + + logger->info("IflytopFrontEndService startListen"); +} + +// void IflytopFrontEndService::sendMessage(const string& message) { +// if (!m_initialized) { +// logger->error("IflytopFrontEndService not initialized"); +// return; +// } +// /** +// * @brief 广播消息给所有连接的客户端 +// */ +// logger->debug("uplink msg: {}", message); +// auto clients = m_server->getClients(); +// for (auto& each : clients) { +// if (each) { +// each->sendText(message); +// } +// } +// } + +void IflytopFrontEndService::sendReport(json& report) { + if (!m_initialized) { + logger->error("IflytopFrontEndService not initialized"); + return; + } + /** + * @brief 广播消息给所有连接的客户端 + */ + + report["timeStamp"] = duration_cast(system_clock::now().time_since_epoch()).count(); + logger->debug("uplink msg: {}", report.dump()); + + auto clients = m_report_server->getClients(); + for (auto& each : clients) { + if (each) { + each->sendText(report.dump()); + } + } +} + +void IflytopFrontEndService::onMessageCallback(weak_ptr webSocket, shared_ptr connectionState, const ix::WebSocketMessagePtr& msg) { + if (msg->type == ix::WebSocketMessageType::Open) { + logger->info("New connection"); + logger->info("id : {}", connectionState->getId()); + logger->info("Uri : {}", msg->openInfo.uri); + logger->info("Headers:"); + for (auto it : msg->openInfo.headers) { + logger->info(" {}: {}", it.first, it.second); + } + + m_work_queue->enQueue([this, webSocket]() { onConnect(webSocket); }); + + } else if (msg->type == ix::WebSocketMessageType::Message) { + logger->debug("downlink msg: {}", msg->str); + string msgtext = msg->str; + m_work_queue->enQueue([this, webSocket, msgtext]() { + try { + processRxMessage(webSocket, msgtext); + } catch (const std::exception& e) { + logger->error("catch exception,processRxMessage error: {}", e.what()); + } + }); + + } else if (msg->type == ix::WebSocketMessageType::Close) { + logger->info("{} Closed connection", msg->closeInfo.remote); + m_work_queue->enQueue([this, webSocket]() { onDisconnect(webSocket); }); + } +} +void IflytopFrontEndService::processRxMessage(weak_ptr webSocket, string rxmsg) { + // if (msg->binary) { + // logger->warn("receive binary message,ignore"); + // return; + // } + + string msgtext = rxmsg; + json message; + + try { + json command = json::parse(msgtext); + json receipt; + receipt["messageId"] = command["messageId"]; + receipt["ackcode"] = 0; + receipt["timeStamp"] = duration_cast(system_clock::now().time_since_epoch()).count(); + try { + onMessage(webSocket, command, receipt); + if (command.find("need_receipt") == command.end() || command["need_receipt"]) { + shared_ptr ws = webSocket.lock(); + if (ws) ws->sendText(receipt.dump(1)); + } + } catch (const std::exception& e) { + logger->error("m_iflytopWSService:onMessag,process rx json failed,exception:{},{}", e.what(), msgtext); + if (command.find("need_receipt") == command.end() || command["need_receipt"]) { + shared_ptr ws = webSocket.lock(); + receipt["ackcode"] = err::zecode(err::kparse_json_err); + receipt["ackcodeInfo"] = err::zecode2str(err::kparse_json_err, e.what()); + + if (ws) ws->sendText(receipt.dump(1)); + } + } + + } catch (const std::exception& e) { + logger->error("m_iflytopWSService:onMessag,parse json failed,exception:{},{}", e.what(), msgtext); + return; + } +} diff --git a/appsrc/service/iflytop_front_end_service/iflytop_front_end_service.hpp b/appsrc/service/iflytop_front_end_service/iflytop_front_end_service.hpp new file mode 100644 index 0000000..e2e92da --- /dev/null +++ b/appsrc/service/iflytop_front_end_service/iflytop_front_end_service.hpp @@ -0,0 +1,72 @@ +// +// Created by iflytop +// + +#pragma once +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "appbase/dep.hpp" +/** + * @brief + * + * service: IflytopHardwareWSService + * + * 协议文档 + * https://iflytop1.feishu.cn/docx/XCeWddMyzoktUdx6EeMcOV5HnAb + * 端口号 + * 19001 + * 参考https://iflytop1.feishu.cn/wiki/wikcnukbr3vOdBfrNdnVXX8YkLg + */ + +namespace iflytop { +using namespace std; +using namespace iflytop; +using namespace core; +using namespace ix; +using namespace nlohmann; + +class IflytopFrontEndService : public enable_shared_from_this { + ENABLE_LOGGER(IflytopFrontEndService); + + public: + // nod::signal webSocket, const ix::WebSocketMessagePtr& msg)> onMessage; + nod::signal webSocket)> onConnect; + nod::signal webSocket)> onDisconnect; + + nod::signal webSocket, json& cmd, json& receipt)> onMessage; + + nod::signal onUdpCmdMessage; + + unique_ptr m_work_queue; + + private: + // + // WebSocketServer的使用参考:http://192.168.1.3:3000/z3rd_lib/IXWebSocket/src/branch/master/docs/usage.md + // + shared_ptr m_server; + shared_ptr m_report_server; + bool m_initialized = false; + + public: + void initialize(string ip = "0.0.0.0"); + void startListen(); + + // void sendMessage(const string& message); + void sendReport(json& report); + + + private: + void onMessageCallback(weak_ptr webSocket, shared_ptr connectionState, const ix::WebSocketMessagePtr& msg); + void processRxMessage(weak_ptr webSocket, string rxmsg); +}; +} // namespace iflytop \ No newline at end of file diff --git a/appsrc/service/main_control_service.cpp b/appsrc/service/main_control_service.cpp new file mode 100644 index 0000000..5cd2b0c --- /dev/null +++ b/appsrc/service/main_control_service.cpp @@ -0,0 +1,12 @@ +#include "main_control_service.hpp" +using namespace iflytop; +using namespace core; +using namespace std; +using namespace nlohmann; + +void MainControlService::dosystem(string order, bool dump) { + if (dump) logger->info("do:{}", order); + system(order.c_str()); +} + +void MainControlService::initialize() {}; diff --git a/appsrc/service/main_control_service.hpp b/appsrc/service/main_control_service.hpp new file mode 100644 index 0000000..a35b937 --- /dev/null +++ b/appsrc/service/main_control_service.hpp @@ -0,0 +1,43 @@ +// +// Created by zwsd +// + +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "appbase/dep.hpp" + +/** + * @brief + * + * service: MainControlService + * + * 监听事件: + * 依赖状态: + * 依赖服务: + * 作用: + * + */ + +namespace iflytop { +using namespace std; +using namespace core; +class MainControlService : public enable_shared_from_this { + ENABLE_LOGGER(MainControlService); + + public: + MainControlService() {}; + void initialize(); + + private: + void dosystem(string order, bool dump); +}; +} // namespace iflytop \ No newline at end of file diff --git a/src/app/main.cpp b/src/app/main.cpp deleted file mode 100644 index be837a4..0000000 --- a/src/app/main.cpp +++ /dev/null @@ -1,5 +0,0 @@ -int main(int argc, char const *argv[]) -{ - - return 0; -}