├── CMakeLists.txt ├── spdlog ├── version.h ├── fmt │ ├── ostr.h │ ├── fmt.h │ ├── bundled │ │ ├── LICENSE.rst │ │ ├── locale.h │ │ └── ostream.h │ └── bin_to_hex.h ├── formatter.h ├── details │ ├── console_globals.h │ ├── synchronous_factory.h │ ├── log_msg-inl.h │ ├── log_msg_buffer.h │ ├── log_msg.h │ ├── null_mutex.h │ ├── periodic_worker.h │ ├── backtracer.h │ ├── periodic_worker-inl.h │ ├── log_msg_buffer-inl.h │ ├── file_helper.h │ ├── backtracer-inl.h │ ├── pattern_formatter.h │ ├── os.h │ ├── fmt_helper.h │ ├── circular_q.h │ ├── thread_pool.h │ ├── thread_pool-inl.h │ ├── registry.h │ ├── file_helper-inl.h │ └── mpmc_blocking_q.h ├── sinks │ ├── sink-inl.h │ ├── sink.h │ ├── msvc_sink.h │ ├── basic_file_sink-inl.h │ ├── stdout_color_sinks-inl.h │ ├── null_sink.h │ ├── ostream_sink.h │ ├── base_sink.h │ ├── stdout_color_sinks.h │ ├── basic_file_sink.h │ ├── base_sink-inl.h │ ├── stdout_sinks.h │ ├── dist_sink.h │ ├── rotating_file_sink.h │ ├── stdout_sinks-inl.h │ ├── dup_filter_sink.h │ ├── wincolor_sink.h │ ├── systemd_sink.h │ ├── android_sink.h │ ├── syslog_sink.h │ ├── ansicolor_sink.h │ ├── rotating_file_sink-inl.h │ ├── ansicolor_sink-inl.h │ ├── wincolor_sink-inl.h │ └── daily_file_sink.h ├── common-inl.h ├── async_logger.h ├── async_logger-inl.h ├── spdlog-inl.h ├── async.h ├── tweakme.h ├── logger-inl.h └── common.h ├── log_helper.h ├── example ├── CMakeLists.txt ├── http.h ├── os_common.h └── rttp_asio_file_server.h ├── README.md ├── round_trip_meter.h ├── trip_time_sample.h ├── utp_common.cpp ├── utp_socket_c.h ├── congestion_control.h ├── utp_common.h └── utp_socket.h /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1) 2 | 3 | set(CMAKE_CXX_STANDARD 11) 4 | 5 | include_directories(./) 6 | 7 | file( 8 | GLOB 9 | SRC 10 | ./*.cpp 11 | ) 12 | 13 | add_library(UTPLib ${SRC}) 14 | 15 | add_subdirectory(example) 16 | -------------------------------------------------------------------------------- /spdlog/version.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #define SPDLOG_VER_MAJOR 1 7 | #define SPDLOG_VER_MINOR 4 8 | #define SPDLOG_VER_PATCH 1 9 | 10 | #define SPDLOG_VERSION (SPDLOG_VER_MAJOR * 10000 + SPDLOG_VER_MINOR * 100 + SPDLOG_VER_PATCH) 11 | -------------------------------------------------------------------------------- /spdlog/fmt/ostr.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2016 Gabi Melman. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | // 8 | // include bundled or external copy of fmtlib's ostream support 9 | // 10 | #if !defined(SPDLOG_FMT_EXTERNAL) 11 | #ifndef FMT_HEADER_ONLY 12 | #define FMT_HEADER_ONLY 13 | #endif 14 | #include "bundled/ostream.h" 15 | #include "fmt.h" 16 | #else 17 | #include 18 | #endif 19 | -------------------------------------------------------------------------------- /spdlog/formatter.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include "fmt/fmt.h" 7 | #include "spdlog/details/log_msg.h" 8 | 9 | namespace spdlog { 10 | 11 | class formatter 12 | { 13 | public: 14 | virtual ~formatter() = default; 15 | virtual void format(const details::log_msg &msg, memory_buf_t &dest) = 0; 16 | virtual std::unique_ptr clone() const = 0; 17 | }; 18 | } // namespace spdlog 19 | -------------------------------------------------------------------------------- /spdlog/fmt/fmt.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2016-2018 Gabi Melman. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | 8 | // 9 | // Include a bundled header-only copy of fmtlib or an external one. 10 | // By default spdlog include its own copy. 11 | // 12 | 13 | #if !defined(SPDLOG_FMT_EXTERNAL) 14 | #ifdef SPDLOG_HEADER_ONLY 15 | #ifndef FMT_HEADER_ONLY 16 | #define FMT_HEADER_ONLY 17 | #endif 18 | #endif 19 | #ifndef FMT_USE_WINDOWS_H 20 | #define FMT_USE_WINDOWS_H 0 21 | #endif 22 | #include "bundled/core.h" 23 | #include "bundled/format.h" 24 | #else // SPDLOG_FMT_EXTERNAL is defined - use external fmtlib 25 | #include "fmt/core.h" 26 | #include "fmt/format.h" 27 | #endif 28 | -------------------------------------------------------------------------------- /spdlog/details/console_globals.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include "spdlog/details/null_mutex.h" 7 | #include 8 | 9 | namespace spdlog { 10 | namespace details { 11 | 12 | struct console_mutex 13 | { 14 | using mutex_t = std::mutex; 15 | static mutex_t &mutex() 16 | { 17 | static mutex_t s_mutex; 18 | return s_mutex; 19 | } 20 | }; 21 | 22 | struct console_nullmutex 23 | { 24 | using mutex_t = null_mutex; 25 | static mutex_t &mutex() 26 | { 27 | static mutex_t s_mutex; 28 | return s_mutex; 29 | } 30 | }; 31 | } // namespace details 32 | } // namespace spdlog 33 | -------------------------------------------------------------------------------- /spdlog/sinks/sink-inl.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifndef SPDLOG_HEADER_ONLY 7 | #include "spdlog/sinks/sink.h" 8 | #endif 9 | 10 | #include "spdlog/common.h" 11 | 12 | SPDLOG_INLINE bool spdlog::sinks::sink::should_log(spdlog::level::level_enum msg_level) const 13 | { 14 | return msg_level >= level_.load(std::memory_order_relaxed); 15 | } 16 | 17 | SPDLOG_INLINE void spdlog::sinks::sink::set_level(level::level_enum log_level) 18 | { 19 | level_.store(log_level, std::memory_order_relaxed); 20 | } 21 | 22 | SPDLOG_INLINE spdlog::level::level_enum spdlog::sinks::sink::level() const 23 | { 24 | return static_cast(level_.load(std::memory_order_relaxed)); 25 | } 26 | -------------------------------------------------------------------------------- /spdlog/details/synchronous_factory.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include "registry.h" 7 | 8 | namespace spdlog { 9 | 10 | // Default logger factory- creates synchronous loggers 11 | class logger; 12 | 13 | struct synchronous_factory 14 | { 15 | template 16 | static std::shared_ptr create(std::string logger_name, SinkArgs &&... args) 17 | { 18 | auto sink = std::make_shared(std::forward(args)...); 19 | auto new_logger = std::make_shared(std::move(logger_name), std::move(sink)); 20 | details::registry::instance().initialize_logger(new_logger); 21 | return new_logger; 22 | } 23 | }; 24 | } // namespace spdlog -------------------------------------------------------------------------------- /spdlog/details/log_msg-inl.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifndef SPDLOG_HEADER_ONLY 7 | #include "spdlog/details/log_msg.h" 8 | #endif 9 | 10 | #include "spdlog/details/os.h" 11 | 12 | namespace spdlog { 13 | namespace details { 14 | 15 | SPDLOG_INLINE log_msg::log_msg(spdlog::source_loc loc, string_view_t logger_name, spdlog::level::level_enum lvl, spdlog::string_view_t msg) 16 | : logger_name(logger_name) 17 | , level(lvl) 18 | #ifndef SPDLOG_NO_DATETIME 19 | , time(os::now()) 20 | #endif 21 | 22 | #ifndef SPDLOG_NO_THREAD_ID 23 | , thread_id(os::thread_id()) 24 | #endif 25 | , source(loc) 26 | , payload(msg) 27 | {} 28 | 29 | SPDLOG_INLINE log_msg::log_msg(string_view_t logger_name, spdlog::level::level_enum lvl, spdlog::string_view_t msg) 30 | : log_msg(source_loc{}, logger_name, lvl, msg) 31 | {} 32 | 33 | } // namespace details 34 | } // namespace spdlog 35 | -------------------------------------------------------------------------------- /spdlog/sinks/sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include "spdlog/details/log_msg.h" 7 | #include "spdlog/formatter.h" 8 | 9 | namespace spdlog { 10 | 11 | namespace sinks { 12 | class sink 13 | { 14 | public: 15 | virtual ~sink() = default; 16 | virtual void log(const details::log_msg &msg) = 0; 17 | virtual void flush() = 0; 18 | virtual void set_pattern(const std::string &pattern) = 0; 19 | virtual void set_formatter(std::unique_ptr sink_formatter) = 0; 20 | 21 | void set_level(level::level_enum log_level); 22 | level::level_enum level() const; 23 | bool should_log(level::level_enum msg_level) const; 24 | 25 | protected: 26 | // sink log level - default is all 27 | level_t level_{level::trace}; 28 | }; 29 | 30 | } // namespace sinks 31 | } // namespace spdlog 32 | 33 | #ifdef SPDLOG_HEADER_ONLY 34 | #include "sink-inl.h" 35 | #endif 36 | -------------------------------------------------------------------------------- /spdlog/details/log_msg_buffer.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include "spdlog/details/log_msg.h" 7 | 8 | namespace spdlog { 9 | namespace details { 10 | 11 | // Extend log_msg with internal buffer to store its payload. 12 | // THis is needed since log_msg holds string_views that points to stack data. 13 | 14 | class log_msg_buffer : public log_msg 15 | { 16 | memory_buf_t buffer; 17 | void update_string_views(); 18 | 19 | public: 20 | log_msg_buffer() = default; 21 | explicit log_msg_buffer(const log_msg &orig_msg); 22 | log_msg_buffer(const log_msg_buffer &other); 23 | log_msg_buffer(log_msg_buffer &&other); 24 | log_msg_buffer &operator=(const log_msg_buffer &other); 25 | log_msg_buffer &operator=(log_msg_buffer &&other); 26 | }; 27 | 28 | } // namespace details 29 | } // namespace spdlog 30 | 31 | #ifdef SPDLOG_HEADER_ONLY 32 | #include "log_msg_buffer-inl.h" 33 | #endif 34 | -------------------------------------------------------------------------------- /spdlog/details/log_msg.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include "spdlog/common.h" 7 | #include 8 | 9 | namespace spdlog { 10 | namespace details { 11 | struct log_msg 12 | { 13 | log_msg() = default; 14 | log_msg(source_loc loc, string_view_t logger_name, level::level_enum lvl, string_view_t msg); 15 | log_msg(string_view_t logger_name, level::level_enum lvl, string_view_t msg); 16 | log_msg(const log_msg &other) = default; 17 | 18 | string_view_t logger_name; 19 | level::level_enum level{level::off}; 20 | log_clock::time_point time; 21 | size_t thread_id{0}; 22 | 23 | // wrapping the formatted text with color (updated by pattern_formatter). 24 | mutable size_t color_range_start{0}; 25 | mutable size_t color_range_end{0}; 26 | 27 | source_loc source; 28 | string_view_t payload; 29 | }; 30 | } // namespace details 31 | } // namespace spdlog 32 | 33 | #ifdef SPDLOG_HEADER_ONLY 34 | #include "log_msg-inl.h" 35 | #endif 36 | -------------------------------------------------------------------------------- /log_helper.h: -------------------------------------------------------------------------------- 1 | #ifndef LOG_HELPER_H 2 | #define LOG_HELPER_H 3 | 4 | //#define ENABLE_UTP_LOG 5 | 6 | #ifdef ENABLE_UTP_LOG 7 | 8 | #define SPDLOG_TRACE_ON 9 | #define SPDLOG_DEBUG_ON 10 | 11 | #include "spdlog/spdlog.h" 12 | #include "spdlog/sinks/basic_file_sink.h" 13 | 14 | #define SPDLOG_INFO(logger, ...) logger->info(__VA_ARGS__) 15 | #define SPDLOG_ERROR(logger, ...) logger->error(__VA_ARGS__) 16 | 17 | #define DECLARE_LOG(n, f) static auto logger = spdlog::basic_logger_mt(n, f, true); 18 | 19 | #else 20 | 21 | #define DECLARE_LOG(n, f) ; 22 | 23 | #define SPDLOG_TRACE(logger, ...) ; 24 | #define SPDLOG_DEBUG(logger, ...) ; 25 | #define SPDLOG_INFO(logger, ...) ; 26 | #define SPDLOG_ERROR(logger, ...) ; 27 | 28 | #endif 29 | 30 | #define LOG_TRACE SPDLOG_TRACE 31 | #define LOG_DEBUG SPDLOG_INFO 32 | #define LOG_INFO SPDLOG_INFO 33 | #define LOG_ERROR SPDLOG_ERROR 34 | 35 | 36 | 37 | class LogHelper 38 | { 39 | public: 40 | LogHelper() 41 | { 42 | #ifdef ENABLE_UTP_LOG 43 | spdlog::set_level(spdlog::level::trace); 44 | spdlog::flush_every(std::chrono::seconds(1)); 45 | #endif 46 | } 47 | ~LogHelper() {} 48 | }; 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /spdlog/sinks/msvc_sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2016 Alexander Dalshov. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #if defined(_WIN32) 7 | 8 | #include "spdlog/details/null_mutex.h" 9 | #include "spdlog/sinks/base_sink.h" 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | namespace spdlog { 17 | namespace sinks { 18 | /* 19 | * MSVC sink (logging using OutputDebugStringA) 20 | */ 21 | template 22 | class msvc_sink : public base_sink 23 | { 24 | public: 25 | explicit msvc_sink() {} 26 | 27 | protected: 28 | void sink_it_(const details::log_msg &msg) override 29 | { 30 | 31 | memory_buf_t formatted; 32 | base_sink::formatter_->format(msg, formatted); 33 | OutputDebugStringA(fmt::to_string(formatted).c_str()); 34 | } 35 | 36 | void flush_() override {} 37 | }; 38 | 39 | using msvc_sink_mt = msvc_sink; 40 | using msvc_sink_st = msvc_sink; 41 | 42 | using windebug_sink_mt = msvc_sink_mt; 43 | using windebug_sink_st = msvc_sink_st; 44 | 45 | } // namespace sinks 46 | } // namespace spdlog 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /spdlog/sinks/basic_file_sink-inl.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifndef SPDLOG_HEADER_ONLY 7 | #include "spdlog/sinks/basic_file_sink.h" 8 | #endif 9 | 10 | #include "spdlog/common.h" 11 | #include "spdlog/details/os.h" 12 | 13 | namespace spdlog { 14 | namespace sinks { 15 | 16 | template 17 | SPDLOG_INLINE basic_file_sink::basic_file_sink(const filename_t &filename, bool truncate) 18 | { 19 | file_helper_.open(filename, truncate); 20 | } 21 | 22 | template 23 | SPDLOG_INLINE const filename_t &basic_file_sink::filename() const 24 | { 25 | return file_helper_.filename(); 26 | } 27 | 28 | template 29 | SPDLOG_INLINE void basic_file_sink::sink_it_(const details::log_msg &msg) 30 | { 31 | memory_buf_t formatted; 32 | base_sink::formatter_->format(msg, formatted); 33 | file_helper_.write(formatted); 34 | } 35 | 36 | template 37 | SPDLOG_INLINE void basic_file_sink::flush_() 38 | { 39 | file_helper_.flush(); 40 | } 41 | 42 | } // namespace sinks 43 | } // namespace spdlog 44 | -------------------------------------------------------------------------------- /example/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1) 2 | 3 | set(CMAKE_CXX_STANDARD 11) 4 | 5 | #set(CMAKE_BUILD_TYPE Debug) 6 | 7 | include_directories(../) 8 | 9 | add_executable(HttpUFileServer rttp_asio_file_server.cpp http.cpp) 10 | add_executable(HttpUGetFile rttp_async_file_client.cpp http.cpp) 11 | 12 | IF(${CMAKE_SYSTEM_NAME} MATCHES "Windows") 13 | set(CMAKE_CXX_FLAGS_RELEASE "/O2") 14 | target_link_libraries(HttpUFileServer UTPLib ws2_32.lib) 15 | target_link_libraries(HttpUGetFile UTPLib ws2_32.lib) 16 | ELSE(${CMAKE_SYSTEM_NAME} MATCHES "Windows") 17 | set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-pthread") 18 | 19 | IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") 20 | include_directories(/usr/local/include) 21 | target_link_libraries(HttpUFileServer UTPLib /usr/local/lib/libboost_system.a /usr/local/lib/libboost_filesystem.a) 22 | target_link_libraries(HttpUGetFile UTPLib ) 23 | ELSE(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") 24 | target_link_libraries(HttpUFileServer UTPLib boost_system boost_filesystem) 25 | target_link_libraries(HttpUGetFile UTPLib ) 26 | ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") 27 | ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Windows") 28 | 29 | -------------------------------------------------------------------------------- /spdlog/details/null_mutex.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | // null, no cost dummy "mutex" and dummy "atomic" int 9 | 10 | namespace spdlog { 11 | namespace details { 12 | struct null_mutex 13 | { 14 | void lock() const {} 15 | void unlock() const {} 16 | bool try_lock() const 17 | { 18 | return true; 19 | } 20 | }; 21 | 22 | struct null_atomic_int 23 | { 24 | int value; 25 | null_atomic_int() = default; 26 | 27 | explicit null_atomic_int(int new_value) 28 | : value(new_value) 29 | {} 30 | 31 | int load(std::memory_order = std::memory_order_relaxed) const 32 | { 33 | return value; 34 | } 35 | 36 | void store(int new_value, std::memory_order = std::memory_order_relaxed) 37 | { 38 | value = new_value; 39 | } 40 | 41 | int exchange(int new_value, std::memory_order = std::memory_order_relaxed) 42 | { 43 | std::swap(new_value, value); 44 | return new_value; // return value before the call 45 | } 46 | }; 47 | 48 | } // namespace details 49 | } // namespace spdlog 50 | -------------------------------------------------------------------------------- /spdlog/details/periodic_worker.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | // periodic worker thread - periodically executes the given callback function. 7 | // 8 | // RAII over the owned thread: 9 | // creates the thread on construction. 10 | // stops and joins the thread on destruction (if the thread is executing a callback, wait for it to finish first). 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | namespace spdlog { 18 | namespace details { 19 | 20 | class periodic_worker 21 | { 22 | public: 23 | periodic_worker(const std::function &callback_fun, std::chrono::seconds interval); 24 | periodic_worker(const periodic_worker &) = delete; 25 | periodic_worker &operator=(const periodic_worker &) = delete; 26 | // stop the worker thread and join it 27 | ~periodic_worker(); 28 | 29 | private: 30 | bool active_; 31 | std::thread worker_thread_; 32 | std::mutex mutex_; 33 | std::condition_variable cv_; 34 | }; 35 | } // namespace details 36 | } // namespace spdlog 37 | 38 | #ifdef SPDLOG_HEADER_ONLY 39 | #include "periodic_worker-inl.h" 40 | #endif 41 | -------------------------------------------------------------------------------- /spdlog/details/backtracer.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include "spdlog/details/log_msg_buffer.h" 7 | #include "spdlog/details/circular_q.h" 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | // Store log messages in circular buffer. 14 | // Useful for storing debug data in case of error/warning happens. 15 | 16 | namespace spdlog { 17 | namespace details { 18 | class backtracer 19 | { 20 | mutable std::mutex mutex_; 21 | std::atomic enabled_{false}; 22 | circular_q messages_; 23 | 24 | public: 25 | backtracer() = default; 26 | backtracer(const backtracer &other); 27 | 28 | backtracer(backtracer &&other) SPDLOG_NOEXCEPT; 29 | backtracer &operator=(backtracer other); 30 | 31 | void enable(size_t size); 32 | void disable(); 33 | bool enabled() const; 34 | explicit operator bool() const; 35 | void push_back(const log_msg &msg); 36 | 37 | // pop all items in the q and apply the given fun on each of them. 38 | void foreach_pop(std::function fun); 39 | }; 40 | 41 | } // namespace details 42 | } // namespace spdlog 43 | 44 | #ifdef SPDLOG_HEADER_ONLY 45 | #include "backtracer-inl.h" 46 | #endif -------------------------------------------------------------------------------- /spdlog/sinks/stdout_color_sinks-inl.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifndef SPDLOG_HEADER_ONLY 7 | #include "spdlog/sinks/stdout_color_sinks.h" 8 | #endif 9 | 10 | #include "spdlog/logger.h" 11 | #include "spdlog/common.h" 12 | 13 | namespace spdlog { 14 | 15 | template 16 | SPDLOG_INLINE std::shared_ptr stdout_color_mt(const std::string &logger_name, color_mode mode) 17 | { 18 | return Factory::template create(logger_name, mode); 19 | } 20 | 21 | template 22 | SPDLOG_INLINE std::shared_ptr stdout_color_st(const std::string &logger_name, color_mode mode) 23 | { 24 | return Factory::template create(logger_name, mode); 25 | } 26 | 27 | template 28 | SPDLOG_INLINE std::shared_ptr stderr_color_mt(const std::string &logger_name, color_mode mode) 29 | { 30 | return Factory::template create(logger_name, mode); 31 | } 32 | 33 | template 34 | SPDLOG_INLINE std::shared_ptr stderr_color_st(const std::string &logger_name, color_mode mode) 35 | { 36 | return Factory::template create(logger_name, mode); 37 | } 38 | } // namespace spdlog -------------------------------------------------------------------------------- /spdlog/sinks/null_sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include "spdlog/details/null_mutex.h" 7 | #include "spdlog/sinks/base_sink.h" 8 | #include "spdlog/details/synchronous_factory.h" 9 | 10 | #include 11 | 12 | namespace spdlog { 13 | namespace sinks { 14 | 15 | template 16 | class null_sink : public base_sink 17 | { 18 | protected: 19 | void sink_it_(const details::log_msg &) override {} 20 | void flush_() override {} 21 | }; 22 | 23 | using null_sink_mt = null_sink; 24 | using null_sink_st = null_sink; 25 | 26 | } // namespace sinks 27 | 28 | template 29 | inline std::shared_ptr null_logger_mt(const std::string &logger_name) 30 | { 31 | auto null_logger = Factory::template create(logger_name); 32 | null_logger->set_level(level::off); 33 | return null_logger; 34 | } 35 | 36 | template 37 | inline std::shared_ptr null_logger_st(const std::string &logger_name) 38 | { 39 | auto null_logger = Factory::template create(logger_name); 40 | null_logger->set_level(level::off); 41 | return null_logger; 42 | } 43 | 44 | } // namespace spdlog 45 | -------------------------------------------------------------------------------- /spdlog/details/periodic_worker-inl.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifndef SPDLOG_HEADER_ONLY 7 | #include "spdlog/details/periodic_worker.h" 8 | #endif 9 | 10 | namespace spdlog { 11 | namespace details { 12 | 13 | SPDLOG_INLINE periodic_worker::periodic_worker(const std::function &callback_fun, std::chrono::seconds interval) 14 | { 15 | active_ = (interval > std::chrono::seconds::zero()); 16 | if (!active_) 17 | { 18 | return; 19 | } 20 | 21 | worker_thread_ = std::thread([this, callback_fun, interval]() { 22 | for (;;) 23 | { 24 | std::unique_lock lock(this->mutex_); 25 | if (this->cv_.wait_for(lock, interval, [this] { return !this->active_; })) 26 | { 27 | return; // active_ == false, so exit this thread 28 | } 29 | callback_fun(); 30 | } 31 | }); 32 | } 33 | 34 | // stop the worker thread and join it 35 | SPDLOG_INLINE periodic_worker::~periodic_worker() 36 | { 37 | if (worker_thread_.joinable()) 38 | { 39 | { 40 | std::lock_guard lock(mutex_); 41 | active_ = false; 42 | } 43 | cv_.notify_one(); 44 | worker_thread_.join(); 45 | } 46 | } 47 | 48 | } // namespace details 49 | } // namespace spdlog 50 | -------------------------------------------------------------------------------- /spdlog/sinks/ostream_sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include "spdlog/details/null_mutex.h" 7 | #include "spdlog/sinks/base_sink.h" 8 | 9 | #include 10 | #include 11 | 12 | namespace spdlog { 13 | namespace sinks { 14 | template 15 | class ostream_sink final : public base_sink 16 | { 17 | public: 18 | explicit ostream_sink(std::ostream &os, bool force_flush = false) 19 | : ostream_(os) 20 | , force_flush_(force_flush) 21 | {} 22 | ostream_sink(const ostream_sink &) = delete; 23 | ostream_sink &operator=(const ostream_sink &) = delete; 24 | 25 | protected: 26 | void sink_it_(const details::log_msg &msg) override 27 | { 28 | memory_buf_t formatted; 29 | base_sink::formatter_->format(msg, formatted); 30 | ostream_.write(formatted.data(), static_cast(formatted.size())); 31 | if (force_flush_) 32 | { 33 | ostream_.flush(); 34 | } 35 | } 36 | 37 | void flush_() override 38 | { 39 | ostream_.flush(); 40 | } 41 | 42 | std::ostream &ostream_; 43 | bool force_flush_; 44 | }; 45 | 46 | using ostream_sink_mt = ostream_sink; 47 | using ostream_sink_st = ostream_sink; 48 | 49 | } // namespace sinks 50 | } // namespace spdlog 51 | -------------------------------------------------------------------------------- /spdlog/fmt/bundled/LICENSE.rst: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 - present, Victor Zverovich 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | --- Optional exception to the license --- 23 | 24 | As an exception, if, as a result of your compiling your source code, portions 25 | of this Software are embedded into a machine-executable object form of such 26 | source code, you may redistribute such embedded portions in such object form 27 | without including the above copyright and permission notices. 28 | -------------------------------------------------------------------------------- /spdlog/sinks/base_sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | // 6 | // base sink templated over a mutex (either dummy or real) 7 | // concrete implementation should override the sink_it_() and flush_() methods. 8 | // locking is taken care of in this class - no locking needed by the 9 | // implementers.. 10 | // 11 | 12 | #include "spdlog/common.h" 13 | #include "spdlog/details/log_msg.h" 14 | #include "spdlog/sinks/sink.h" 15 | 16 | namespace spdlog { 17 | namespace sinks { 18 | template 19 | class base_sink : public sink 20 | { 21 | public: 22 | base_sink(); 23 | explicit base_sink(std::unique_ptr formatter); 24 | base_sink(const base_sink &) = delete; 25 | base_sink &operator=(const base_sink &) = delete; 26 | void log(const details::log_msg &msg) final; 27 | void flush() final; 28 | void set_pattern(const std::string &pattern) final; 29 | void set_formatter(std::unique_ptr sink_formatter) final; 30 | 31 | protected: 32 | // sink formatter 33 | std::unique_ptr formatter_; 34 | Mutex mutex_; 35 | 36 | virtual void sink_it_(const details::log_msg &msg) = 0; 37 | virtual void flush_() = 0; 38 | virtual void set_pattern_(const std::string &pattern); 39 | virtual void set_formatter_(std::unique_ptr sink_formatter); 40 | }; 41 | } // namespace sinks 42 | } // namespace spdlog 43 | 44 | #ifdef SPDLOG_HEADER_ONLY 45 | #include "base_sink-inl.h" 46 | #endif 47 | -------------------------------------------------------------------------------- /spdlog/common-inl.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifndef SPDLOG_HEADER_ONLY 7 | #include "spdlog/common.h" 8 | #endif 9 | 10 | namespace spdlog { 11 | namespace level { 12 | static string_view_t level_string_views[] SPDLOG_LEVEL_NAMES; 13 | 14 | static const char *short_level_names[] SPDLOG_SHORT_LEVEL_NAMES; 15 | 16 | SPDLOG_INLINE string_view_t &to_string_view(spdlog::level::level_enum l) SPDLOG_NOEXCEPT 17 | { 18 | return level_string_views[l]; 19 | } 20 | 21 | SPDLOG_INLINE const char *to_short_c_str(spdlog::level::level_enum l) SPDLOG_NOEXCEPT 22 | { 23 | return short_level_names[l]; 24 | } 25 | 26 | SPDLOG_INLINE spdlog::level::level_enum from_str(const std::string &name) SPDLOG_NOEXCEPT 27 | { 28 | int level = 0; 29 | for (const auto &level_str : level_string_views) 30 | { 31 | if (level_str == name) 32 | { 33 | return static_cast(level); 34 | } 35 | level++; 36 | } 37 | return level::off; 38 | } 39 | } // namespace level 40 | 41 | SPDLOG_INLINE spdlog_ex::spdlog_ex(std::string msg) 42 | : msg_(std::move(msg)) 43 | {} 44 | 45 | SPDLOG_INLINE spdlog_ex::spdlog_ex(const std::string &msg, int last_errno) 46 | { 47 | memory_buf_t outbuf; 48 | fmt::format_system_error(outbuf, last_errno, msg); 49 | msg_ = fmt::to_string(outbuf); 50 | } 51 | 52 | SPDLOG_INLINE const char *spdlog_ex::what() const SPDLOG_NOEXCEPT 53 | { 54 | return msg_.c_str(); 55 | } 56 | 57 | } // namespace spdlog 58 | -------------------------------------------------------------------------------- /spdlog/sinks/stdout_color_sinks.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifdef _WIN32 7 | #include "spdlog/sinks/wincolor_sink.h" 8 | #else 9 | #include "spdlog/sinks/ansicolor_sink.h" 10 | #endif 11 | 12 | #include "spdlog/details/synchronous_factory.h" 13 | 14 | namespace spdlog { 15 | namespace sinks { 16 | #ifdef _WIN32 17 | using stdout_color_sink_mt = wincolor_stdout_sink_mt; 18 | using stdout_color_sink_st = wincolor_stdout_sink_st; 19 | using stderr_color_sink_mt = wincolor_stderr_sink_mt; 20 | using stderr_color_sink_st = wincolor_stderr_sink_st; 21 | #else 22 | using stdout_color_sink_mt = ansicolor_stdout_sink_mt; 23 | using stdout_color_sink_st = ansicolor_stdout_sink_st; 24 | using stderr_color_sink_mt = ansicolor_stderr_sink_mt; 25 | using stderr_color_sink_st = ansicolor_stderr_sink_st; 26 | #endif 27 | } // namespace sinks 28 | 29 | template 30 | std::shared_ptr stdout_color_mt(const std::string &logger_name, color_mode mode = color_mode::automatic); 31 | 32 | template 33 | std::shared_ptr stdout_color_st(const std::string &logger_name, color_mode mode = color_mode::automatic); 34 | 35 | template 36 | std::shared_ptr stderr_color_mt(const std::string &logger_name, color_mode mode = color_mode::automatic); 37 | 38 | template 39 | std::shared_ptr stderr_color_st(const std::string &logger_name, color_mode mode = color_mode::automatic); 40 | 41 | } // namespace spdlog 42 | 43 | #ifdef SPDLOG_HEADER_ONLY 44 | #include "stdout_color_sinks-inl.h" 45 | #endif 46 | -------------------------------------------------------------------------------- /spdlog/sinks/basic_file_sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include "spdlog/details/file_helper.h" 7 | #include "spdlog/details/null_mutex.h" 8 | #include "spdlog/sinks/base_sink.h" 9 | #include "spdlog/details/synchronous_factory.h" 10 | 11 | #include 12 | #include 13 | 14 | namespace spdlog { 15 | namespace sinks { 16 | /* 17 | * Trivial file sink with single file as target 18 | */ 19 | template 20 | class basic_file_sink final : public base_sink 21 | { 22 | public: 23 | explicit basic_file_sink(const filename_t &filename, bool truncate = false); 24 | const filename_t &filename() const; 25 | 26 | protected: 27 | void sink_it_(const details::log_msg &msg) override; 28 | void flush_() override; 29 | 30 | private: 31 | details::file_helper file_helper_; 32 | }; 33 | 34 | using basic_file_sink_mt = basic_file_sink; 35 | using basic_file_sink_st = basic_file_sink; 36 | 37 | } // namespace sinks 38 | 39 | // 40 | // factory functions 41 | // 42 | template 43 | inline std::shared_ptr basic_logger_mt(const std::string &logger_name, const filename_t &filename, bool truncate = false) 44 | { 45 | return Factory::template create(logger_name, filename, truncate); 46 | } 47 | 48 | template 49 | inline std::shared_ptr basic_logger_st(const std::string &logger_name, const filename_t &filename, bool truncate = false) 50 | { 51 | return Factory::template create(logger_name, filename, truncate); 52 | } 53 | 54 | } // namespace spdlog 55 | 56 | #ifdef SPDLOG_HEADER_ONLY 57 | #include "basic_file_sink-inl.h" 58 | #endif -------------------------------------------------------------------------------- /spdlog/details/log_msg_buffer-inl.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifndef SPDLOG_HEADER_ONLY 7 | #include "spdlog/details/log_msg_buffer.h" 8 | #endif 9 | 10 | namespace spdlog { 11 | namespace details { 12 | 13 | SPDLOG_INLINE log_msg_buffer::log_msg_buffer(const log_msg &orig_msg) 14 | : log_msg{orig_msg} 15 | { 16 | buffer.append(logger_name.begin(), logger_name.end()); 17 | buffer.append(payload.begin(), payload.end()); 18 | update_string_views(); 19 | } 20 | 21 | SPDLOG_INLINE log_msg_buffer::log_msg_buffer(const log_msg_buffer &other) 22 | : log_msg{other} 23 | { 24 | buffer.append(logger_name.begin(), logger_name.end()); 25 | buffer.append(payload.begin(), payload.end()); 26 | update_string_views(); 27 | } 28 | 29 | SPDLOG_INLINE log_msg_buffer::log_msg_buffer(log_msg_buffer &&other) 30 | : log_msg{std::move(other)} 31 | , buffer{std::move(other.buffer)} 32 | { 33 | update_string_views(); 34 | } 35 | 36 | SPDLOG_INLINE log_msg_buffer &log_msg_buffer::operator=(const log_msg_buffer &other) 37 | { 38 | log_msg::operator=(other); 39 | buffer.clear(); 40 | buffer.append(other.buffer.data(), other.buffer.data() + other.buffer.size()); 41 | update_string_views(); 42 | return *this; 43 | } 44 | 45 | SPDLOG_INLINE log_msg_buffer &log_msg_buffer::operator=(log_msg_buffer &&other) 46 | { 47 | log_msg::operator=(std::move(other)); 48 | buffer = std::move(other.buffer); 49 | update_string_views(); 50 | return *this; 51 | } 52 | 53 | SPDLOG_INLINE void log_msg_buffer::update_string_views() 54 | { 55 | logger_name = string_view_t{buffer.data(), logger_name.size()}; 56 | payload = string_view_t{buffer.data() + logger_name.size(), payload.size()}; 57 | } 58 | 59 | } // namespace details 60 | } // namespace spdlog 61 | -------------------------------------------------------------------------------- /spdlog/details/file_helper.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include "spdlog/common.h" 7 | #include 8 | 9 | namespace spdlog { 10 | namespace details { 11 | 12 | // Helper class for file sinks. 13 | // When failing to open a file, retry several times(5) with a delay interval(10 ms). 14 | // Throw spdlog_ex exception on errors. 15 | 16 | class file_helper 17 | { 18 | public: 19 | explicit file_helper() = default; 20 | 21 | file_helper(const file_helper &) = delete; 22 | file_helper &operator=(const file_helper &) = delete; 23 | ~file_helper(); 24 | 25 | void open(const filename_t &fname, bool truncate = false); 26 | void reopen(bool truncate); 27 | void flush(); 28 | void close(); 29 | void write(const memory_buf_t &buf); 30 | size_t size() const; 31 | const filename_t &filename() const; 32 | static bool file_exists(const filename_t &fname); 33 | 34 | // 35 | // return file path and its extension: 36 | // 37 | // "mylog.txt" => ("mylog", ".txt") 38 | // "mylog" => ("mylog", "") 39 | // "mylog." => ("mylog.", "") 40 | // "/dir1/dir2/mylog.txt" => ("/dir1/dir2/mylog", ".txt") 41 | // 42 | // the starting dot in filenames is ignored (hidden files): 43 | // 44 | // ".mylog" => (".mylog". "") 45 | // "my_folder/.mylog" => ("my_folder/.mylog", "") 46 | // "my_folder/.mylog.txt" => ("my_folder/.mylog", ".txt") 47 | static std::tuple split_by_extension(const filename_t &fname); 48 | 49 | private: 50 | const int open_tries = 5; 51 | const int open_interval = 10; 52 | std::FILE *fd_{nullptr}; 53 | filename_t _filename; 54 | }; 55 | } // namespace details 56 | } // namespace spdlog 57 | 58 | #ifdef SPDLOG_HEADER_ONLY 59 | #include "file_helper-inl.h" 60 | #endif 61 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # utp - A Easy-to-Use uTorrent Transport Protocol Library. 2 | 3 | [uTP](http://www.bittorrent.org/beps/bep_0029.html) (uTorrent transport protocol) is a transport protocol which uses [Low Extra Delay Background Transport (LEDBAT)](http://datatracker.ietf.org/wg/ledbat/charter/) for its congestion controller. 4 | 5 | LEDBAT congestion control has the following goals: 6 | 7 | 1. Try to use all available bandwidth, and to maintain a low queueing delay when no other traffic is present. 8 | 2. Limit the queuing delay it adds to that induced by other traffic. 9 | 3. To yield quickly to standard TCP that share the same bottleneck link. 10 | 11 | ## The API 12 | 13 | [API Doc](api_doc.md) 14 | 15 | ## Building 16 | 17 | ### Linux/MACOSX 18 | cmake ./ 19 | 20 | make 21 | 22 | ### Windows 23 | cmake ./ 24 | 25 | open Project.sln with visual studio 26 | 27 | ## License 28 | 29 | utp is released under the MIT license. 30 | 31 | Copyright (c) 2020 LibEasyGet, RTTTECH, Inc. 32 | 33 | 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: 34 | 35 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 36 | 37 | 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. 38 | -------------------------------------------------------------------------------- /spdlog/sinks/base_sink-inl.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifndef SPDLOG_HEADER_ONLY 7 | #include "spdlog/sinks/base_sink.h" 8 | #endif 9 | 10 | #include "spdlog/common.h" 11 | #include "spdlog/details/pattern_formatter.h" 12 | 13 | #include 14 | 15 | template 16 | SPDLOG_INLINE spdlog::sinks::base_sink::base_sink() 17 | : formatter_{details::make_unique()} 18 | {} 19 | 20 | template 21 | SPDLOG_INLINE spdlog::sinks::base_sink::base_sink(std::unique_ptr formatter) 22 | : formatter_{std::move(formatter)} 23 | {} 24 | 25 | template 26 | void SPDLOG_INLINE spdlog::sinks::base_sink::log(const details::log_msg &msg) 27 | { 28 | std::lock_guard lock(mutex_); 29 | sink_it_(msg); 30 | } 31 | 32 | template 33 | void SPDLOG_INLINE spdlog::sinks::base_sink::flush() 34 | { 35 | std::lock_guard lock(mutex_); 36 | flush_(); 37 | } 38 | 39 | template 40 | void SPDLOG_INLINE spdlog::sinks::base_sink::set_pattern(const std::string &pattern) 41 | { 42 | std::lock_guard lock(mutex_); 43 | set_pattern_(pattern); 44 | } 45 | 46 | template 47 | void SPDLOG_INLINE spdlog::sinks::base_sink::set_formatter(std::unique_ptr sink_formatter) 48 | { 49 | std::lock_guard lock(mutex_); 50 | set_formatter_(std::move(sink_formatter)); 51 | } 52 | 53 | template 54 | void SPDLOG_INLINE spdlog::sinks::base_sink::set_pattern_(const std::string &pattern) 55 | { 56 | set_formatter_(details::make_unique(pattern)); 57 | } 58 | 59 | template 60 | void SPDLOG_INLINE spdlog::sinks::base_sink::set_formatter_(std::unique_ptr sink_formatter) 61 | { 62 | formatter_ = std::move(sink_formatter); 63 | } 64 | -------------------------------------------------------------------------------- /spdlog/details/backtracer-inl.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifndef SPDLOG_HEADER_ONLY 7 | #include "spdlog/details/backtracer.h" 8 | #endif 9 | namespace spdlog { 10 | namespace details { 11 | SPDLOG_INLINE backtracer::backtracer(const backtracer &other) 12 | { 13 | std::lock_guard lock(other.mutex_); 14 | enabled_ = other.enabled(); 15 | messages_ = other.messages_; 16 | } 17 | 18 | SPDLOG_INLINE backtracer::backtracer(backtracer &&other) SPDLOG_NOEXCEPT 19 | { 20 | std::lock_guard lock(other.mutex_); 21 | enabled_ = other.enabled(); 22 | messages_ = std::move(other.messages_); 23 | } 24 | 25 | SPDLOG_INLINE backtracer &backtracer::operator=(backtracer other) 26 | { 27 | std::lock_guard lock(mutex_); 28 | enabled_ = other.enabled(); 29 | messages_ = other.messages_; 30 | return *this; 31 | } 32 | 33 | SPDLOG_INLINE void backtracer::enable(size_t size) 34 | { 35 | std::lock_guard lock{mutex_}; 36 | enabled_.store(true, std::memory_order_relaxed); 37 | messages_ = circular_q{size}; 38 | } 39 | 40 | SPDLOG_INLINE void backtracer::disable() 41 | { 42 | std::lock_guard lock{mutex_}; 43 | enabled_.store(false, std::memory_order_relaxed); 44 | } 45 | 46 | SPDLOG_INLINE bool backtracer::enabled() const 47 | { 48 | return enabled_.load(std::memory_order_relaxed); 49 | } 50 | 51 | SPDLOG_INLINE backtracer::operator bool() const 52 | { 53 | return enabled(); 54 | } 55 | 56 | SPDLOG_INLINE void backtracer::push_back(const log_msg &msg) 57 | { 58 | std::lock_guard lock{mutex_}; 59 | messages_.push_back(log_msg_buffer{msg}); 60 | } 61 | 62 | // pop all items in the q and apply the given fun on each of them. 63 | SPDLOG_INLINE void backtracer::foreach_pop(std::function fun) 64 | { 65 | std::lock_guard lock{mutex_}; 66 | while (!messages_.empty()) 67 | { 68 | auto &front_msg = messages_.front(); 69 | fun(front_msg); 70 | messages_.pop_front(); 71 | } 72 | } 73 | } // namespace details 74 | } // namespace spdlog 75 | -------------------------------------------------------------------------------- /spdlog/sinks/stdout_sinks.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include "spdlog/details/console_globals.h" 7 | #include "spdlog/details/synchronous_factory.h" 8 | #include "spdlog/sinks/sink.h" 9 | #include 10 | 11 | namespace spdlog { 12 | 13 | namespace sinks { 14 | 15 | template 16 | class stdout_sink_base : public sink 17 | { 18 | public: 19 | using mutex_t = typename ConsoleMutex::mutex_t; 20 | explicit stdout_sink_base(FILE *file); 21 | ~stdout_sink_base() override = default; 22 | stdout_sink_base(const stdout_sink_base &other) = delete; 23 | stdout_sink_base &operator=(const stdout_sink_base &other) = delete; 24 | 25 | void log(const details::log_msg &msg) override; 26 | void flush() override; 27 | void set_pattern(const std::string &pattern) override; 28 | 29 | void set_formatter(std::unique_ptr sink_formatter) override; 30 | 31 | protected: 32 | mutex_t &mutex_; 33 | FILE *file_; 34 | std::unique_ptr formatter_; 35 | }; 36 | 37 | template 38 | class stdout_sink : public stdout_sink_base 39 | { 40 | public: 41 | stdout_sink(); 42 | }; 43 | 44 | template 45 | class stderr_sink : public stdout_sink_base 46 | { 47 | public: 48 | stderr_sink(); 49 | }; 50 | 51 | using stdout_sink_mt = stdout_sink; 52 | using stdout_sink_st = stdout_sink; 53 | 54 | using stderr_sink_mt = stderr_sink; 55 | using stderr_sink_st = stderr_sink; 56 | 57 | } // namespace sinks 58 | 59 | // factory methods 60 | template 61 | std::shared_ptr stdout_logger_mt(const std::string &logger_name); 62 | 63 | template 64 | std::shared_ptr stdout_logger_st(const std::string &logger_name); 65 | 66 | template 67 | std::shared_ptr stderr_logger_mt(const std::string &logger_name); 68 | 69 | template 70 | std::shared_ptr stderr_logger_st(const std::string &logger_name); 71 | 72 | } // namespace spdlog 73 | 74 | #ifdef SPDLOG_HEADER_ONLY 75 | #include "stdout_sinks-inl.h" 76 | #endif 77 | -------------------------------------------------------------------------------- /spdlog/async_logger.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | // Fast asynchronous logger. 7 | // Uses pre allocated queue. 8 | // Creates a single back thread to pop messages from the queue and log them. 9 | // 10 | // Upon each log write the logger: 11 | // 1. Checks if its log level is enough to log the message 12 | // 2. Push a new copy of the message to a queue (or block the caller until 13 | // space is available in the queue) 14 | // Upon destruction, logs all remaining messages in the queue before 15 | // destructing.. 16 | 17 | #include "spdlog/logger.h" 18 | 19 | namespace spdlog { 20 | 21 | // Async overflow policy - block by default. 22 | enum class async_overflow_policy 23 | { 24 | block, // Block until message can be enqueued 25 | overrun_oldest // Discard oldest message in the queue if full when trying to 26 | // add new item. 27 | }; 28 | 29 | namespace details { 30 | class thread_pool; 31 | } 32 | 33 | class async_logger final : public std::enable_shared_from_this, public logger 34 | { 35 | friend class details::thread_pool; 36 | 37 | public: 38 | template 39 | async_logger(std::string logger_name, It begin, It end, std::weak_ptr tp, 40 | async_overflow_policy overflow_policy = async_overflow_policy::block) 41 | : logger(std::move(logger_name), begin, end) 42 | , thread_pool_(std::move(tp)) 43 | , overflow_policy_(overflow_policy) 44 | {} 45 | 46 | async_logger(std::string logger_name, sinks_init_list sinks_list, std::weak_ptr tp, 47 | async_overflow_policy overflow_policy = async_overflow_policy::block); 48 | 49 | async_logger(std::string logger_name, sink_ptr single_sink, std::weak_ptr tp, 50 | async_overflow_policy overflow_policy = async_overflow_policy::block); 51 | 52 | std::shared_ptr clone(std::string new_name) override; 53 | 54 | protected: 55 | void sink_it_(const details::log_msg &msg) override; 56 | void flush_() override; 57 | void backend_sink_it_(const details::log_msg &incoming_log_msg); 58 | void backend_flush_(); 59 | 60 | private: 61 | std::weak_ptr thread_pool_; 62 | async_overflow_policy overflow_policy_; 63 | }; 64 | } // namespace spdlog 65 | 66 | #ifdef SPDLOG_HEADER_ONLY 67 | #include "async_logger-inl.h" 68 | #endif 69 | -------------------------------------------------------------------------------- /round_trip_meter.h: -------------------------------------------------------------------------------- 1 | #ifndef __ROUND_TRIP_METER_H__ 2 | #define __ROUND_TRIP_METER_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class RoundTripMeter 10 | { 11 | public: 12 | virtual void OnPacketLost() = 0; 13 | virtual void OnPacketAcked() = 0; 14 | virtual void OnPacketAcked(int64_t rtt) = 0; 15 | virtual int64_t GetTimeoutValue() = 0; 16 | virtual int64_t GetRTT() = 0; 17 | virtual void SetBeta(double beta) = 0; 18 | virtual ~RoundTripMeter() {} 19 | }; 20 | 21 | class SimpleRoundTripMeter : public RoundTripMeter 22 | { 23 | public: 24 | const uint32_t MAX_RTT = 8 * 1000 * 1000; 25 | const uint32_t INIT_RTT = 1 * 1000 * 1000; 26 | 27 | SimpleRoundTripMeter() : m_bFirstTime(true), m_nSRTT(INIT_RTT), m_nRTTVar(0), m_nRTO(INIT_RTT), m_dbBeta(2), m_dbMinBeta(2), m_nContinusTimeoutTimes(0){} 28 | virtual ~SimpleRoundTripMeter() {} 29 | 30 | virtual void OnPacketLost() 31 | { 32 | 33 | if (++m_nContinusTimeoutTimes >= 10) { 34 | m_nContinusTimeoutTimes = 0; 35 | m_dbBeta *= 2; 36 | if (m_dbBeta > 1024) { 37 | m_dbBeta = 1024; 38 | } 39 | } 40 | } 41 | 42 | virtual void OnPacketAcked() 43 | { 44 | m_nContinusTimeoutTimes = 0; 45 | m_dbBeta = m_dbMinBeta; 46 | } 47 | 48 | virtual void OnPacketAcked(int64_t rtt) 49 | { 50 | if (rtt <= 0) return; 51 | 52 | /* 53 | m_deqRtt.push_back(rtt); 54 | if (m_deqRtt.size() > 1000) { 55 | m_deqRtt.pop_front(); 56 | } 57 | */ 58 | 59 | m_nContinusTimeoutTimes = 0; 60 | m_dbBeta = m_dbMinBeta; 61 | 62 | if (m_bFirstTime) { 63 | m_bFirstTime = false; 64 | m_nRTTVar = rtt / 2; 65 | m_nSRTT = rtt; 66 | m_nRTO = m_nSRTT + 4* m_nRTTVar; 67 | } 68 | else { 69 | m_nRTTVar = 3 * m_nRTTVar / 4 + abs(m_nSRTT - rtt) / 4; 70 | m_nSRTT = 7 * m_nSRTT / 8 + rtt / 8; 71 | m_nRTO = m_nSRTT + 4 * m_nRTTVar; 72 | } 73 | 74 | if (m_nRTO > MAX_RTT) { 75 | m_nRTO = MAX_RTT; 76 | } 77 | 78 | 79 | //std::cout << "raw ttt: "< m_deqRtt;//for test 106 | }; 107 | 108 | #endif -------------------------------------------------------------------------------- /trip_time_sample.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | const int DELAY_BASE_SIZE = 2;//last 2 minutes 8 | const int INSTANT_DELAY_SIZE = 4; 9 | 10 | inline bool DelayLessThan(uint32_t lhs, uint32_t rhs) 11 | { 12 | uint32_t mask = 0xFFFFFFFF; 13 | 14 | const uint32_t dist_down = (lhs - rhs) & mask; 15 | const uint32_t dist_up = (rhs - lhs) & mask; 16 | 17 | return dist_up < dist_down; 18 | } 19 | 20 | class DelaySampleHistroy { 21 | 22 | public: 23 | DelaySampleHistroy() 24 | : 25 | m_nLastUpdateBase(0), 26 | m_nDelayBase(100*1000), 27 | m_nCurMinuteDelayBase(100*1000) 28 | { 29 | 30 | } 31 | 32 | uint32_t GetBase() 33 | { 34 | return m_nDelayBase; 35 | } 36 | 37 | 38 | void AddSample(uint32_t sample, uint64_t nCurTime) 39 | { 40 | 41 | if (m_deqDelayBase.size() == 0) { 42 | for (size_t i = 0; i < DELAY_BASE_SIZE; i++) { 43 | // if we don't have a value, set it to the current sample 44 | m_deqDelayBase.push_back(sample); 45 | } 46 | m_nDelayBase = sample; 47 | m_nCurMinuteDelayBase = sample; 48 | m_nLastUpdateBase = nCurTime; 49 | } 50 | else { 51 | if (DelayLessThan(sample, m_nCurMinuteDelayBase)) { 52 | m_nCurMinuteDelayBase = sample; 53 | } 54 | 55 | if (DelayLessThan(sample, m_nDelayBase)) { 56 | 57 | m_nDelayBase = sample; 58 | } 59 | 60 | const uint32_t delay = sample - m_nDelayBase; 61 | 62 | m_deqInstantDelay.push_back(delay); 63 | if (m_deqInstantDelay.size() > INSTANT_DELAY_SIZE) 64 | m_deqInstantDelay.pop_front(); 65 | 66 | if (nCurTime - m_nLastUpdateBase > 60 * 1000) { 67 | m_nLastUpdateBase = nCurTime; 68 | 69 | m_deqDelayBase.push_back(m_nCurMinuteDelayBase); 70 | if (m_deqDelayBase.size() > DELAY_BASE_SIZE) 71 | m_deqDelayBase.pop_front(); 72 | 73 | assert(m_deqDelayBase.size() > 0); 74 | m_nDelayBase = m_deqDelayBase[0]; 75 | for (size_t i = 0; i < m_deqDelayBase.size(); i++) { 76 | if (DelayLessThan(m_deqDelayBase[i], m_nDelayBase)) 77 | m_nDelayBase = m_deqDelayBase[i]; 78 | } 79 | } 80 | } 81 | } 82 | 83 | uint32_t GetValue() 84 | { 85 | uint32_t value = 0xFFFFFFFF; 86 | for (size_t i = 0; i < m_deqInstantDelay.size(); i++) { 87 | value = std::min(m_deqInstantDelay[i], value); 88 | } 89 | 90 | return value; 91 | } 92 | 93 | 94 | private: 95 | uint32_t m_nDelayBase; 96 | 97 | uint32_t m_nCurMinuteDelayBase; 98 | std::deque m_deqDelayBase; 99 | uint64_t m_nLastUpdateBase; 100 | 101 | std::deque m_deqInstantDelay; 102 | }; -------------------------------------------------------------------------------- /spdlog/sinks/dist_sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include "base_sink.h" 7 | #include "spdlog/details/log_msg.h" 8 | #include "spdlog/details/null_mutex.h" 9 | #include "spdlog/details/pattern_formatter.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | // Distribution sink (mux). Stores a vector of sinks which get called when log 17 | // is called 18 | 19 | namespace spdlog { 20 | namespace sinks { 21 | 22 | template 23 | class dist_sink : public base_sink 24 | { 25 | public: 26 | dist_sink() = default; 27 | dist_sink(const dist_sink &) = delete; 28 | dist_sink &operator=(const dist_sink &) = delete; 29 | 30 | void add_sink(std::shared_ptr sink) 31 | { 32 | std::lock_guard lock(base_sink::mutex_); 33 | sinks_.push_back(sink); 34 | } 35 | 36 | void remove_sink(std::shared_ptr sink) 37 | { 38 | std::lock_guard lock(base_sink::mutex_); 39 | sinks_.erase(std::remove(sinks_.begin(), sinks_.end(), sink), sinks_.end()); 40 | } 41 | 42 | void set_sinks(std::vector> sinks) 43 | { 44 | std::lock_guard lock(base_sink::mutex_); 45 | sinks_ = std::move(sinks); 46 | } 47 | 48 | std::vector> &sinks() 49 | { 50 | return sinks_; 51 | } 52 | 53 | protected: 54 | void sink_it_(const details::log_msg &msg) override 55 | { 56 | for (auto &sink : sinks_) 57 | { 58 | if (sink->should_log(msg.level)) 59 | { 60 | sink->log(msg); 61 | } 62 | } 63 | } 64 | 65 | void flush_() override 66 | { 67 | for (auto &sink : sinks_) 68 | { 69 | sink->flush(); 70 | } 71 | } 72 | 73 | void set_pattern_(const std::string &pattern) override 74 | { 75 | set_formatter_(details::make_unique(pattern)); 76 | } 77 | 78 | void set_formatter_(std::unique_ptr sink_formatter) override 79 | { 80 | base_sink::formatter_ = std::move(sink_formatter); 81 | for (auto &sink : sinks_) 82 | { 83 | sink->set_formatter(base_sink::formatter_->clone()); 84 | } 85 | } 86 | std::vector> sinks_; 87 | }; 88 | 89 | using dist_sink_mt = dist_sink; 90 | using dist_sink_st = dist_sink; 91 | 92 | } // namespace sinks 93 | } // namespace spdlog 94 | -------------------------------------------------------------------------------- /spdlog/sinks/rotating_file_sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include "spdlog/sinks/base_sink.h" 7 | #include "spdlog/details/file_helper.h" 8 | #include "spdlog/details/null_mutex.h" 9 | #include "spdlog/details/synchronous_factory.h" 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | namespace spdlog { 16 | namespace sinks { 17 | 18 | // 19 | // Rotating file sink based on size 20 | // 21 | template 22 | class rotating_file_sink final : public base_sink 23 | { 24 | public: 25 | rotating_file_sink(filename_t base_filename, std::size_t max_size, std::size_t max_files, bool rotate_on_open = false); 26 | static filename_t calc_filename(const filename_t &filename, std::size_t index); 27 | const filename_t &filename() const; 28 | 29 | protected: 30 | void sink_it_(const details::log_msg &msg) override; 31 | void flush_() override; 32 | 33 | private: 34 | // Rotate files: 35 | // log.txt -> log.1.txt 36 | // log.1.txt -> log.2.txt 37 | // log.2.txt -> log.3.txt 38 | // log.3.txt -> delete 39 | void rotate_(); 40 | 41 | // delete the target if exists, and rename the src file to target 42 | // return true on success, false otherwise. 43 | bool rename_file(const filename_t &src_filename, const filename_t &target_filename); 44 | 45 | filename_t base_filename_; 46 | std::size_t max_size_; 47 | std::size_t max_files_; 48 | std::size_t current_size_; 49 | details::file_helper file_helper_; 50 | }; 51 | 52 | using rotating_file_sink_mt = rotating_file_sink; 53 | using rotating_file_sink_st = rotating_file_sink; 54 | 55 | } // namespace sinks 56 | 57 | // 58 | // factory functions 59 | // 60 | 61 | template 62 | inline std::shared_ptr rotating_logger_mt( 63 | const std::string &logger_name, const filename_t &filename, size_t max_file_size, size_t max_files, bool rotate_on_open = false) 64 | { 65 | return Factory::template create(logger_name, filename, max_file_size, max_files, rotate_on_open); 66 | } 67 | 68 | template 69 | inline std::shared_ptr rotating_logger_st( 70 | const std::string &logger_name, const filename_t &filename, size_t max_file_size, size_t max_files, bool rotate_on_open = false) 71 | { 72 | return Factory::template create(logger_name, filename, max_file_size, max_files, rotate_on_open); 73 | } 74 | } // namespace spdlog 75 | 76 | #ifdef SPDLOG_HEADER_ONLY 77 | #include "rotating_file_sink-inl.h" 78 | #endif -------------------------------------------------------------------------------- /spdlog/async_logger-inl.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifndef SPDLOG_HEADER_ONLY 7 | #include "spdlog/async_logger.h" 8 | #endif 9 | 10 | #include "spdlog/sinks/sink.h" 11 | #include "spdlog/details/thread_pool.h" 12 | 13 | #include 14 | #include 15 | 16 | SPDLOG_INLINE spdlog::async_logger::async_logger( 17 | std::string logger_name, sinks_init_list sinks_list, std::weak_ptr tp, async_overflow_policy overflow_policy) 18 | : async_logger(std::move(logger_name), sinks_list.begin(), sinks_list.end(), std::move(tp), overflow_policy) 19 | {} 20 | 21 | SPDLOG_INLINE spdlog::async_logger::async_logger( 22 | std::string logger_name, sink_ptr single_sink, std::weak_ptr tp, async_overflow_policy overflow_policy) 23 | : async_logger(std::move(logger_name), {std::move(single_sink)}, std::move(tp), overflow_policy) 24 | {} 25 | 26 | // send the log message to the thread pool 27 | SPDLOG_INLINE void spdlog::async_logger::sink_it_(const details::log_msg &msg) 28 | { 29 | if (auto pool_ptr = thread_pool_.lock()) 30 | { 31 | pool_ptr->post_log(shared_from_this(), msg, overflow_policy_); 32 | } 33 | else 34 | { 35 | SPDLOG_THROW(spdlog_ex("async log: thread pool doesn't exist anymore")); 36 | } 37 | } 38 | 39 | // send flush request to the thread pool 40 | SPDLOG_INLINE void spdlog::async_logger::flush_() 41 | { 42 | if (auto pool_ptr = thread_pool_.lock()) 43 | { 44 | pool_ptr->post_flush(shared_from_this(), overflow_policy_); 45 | } 46 | else 47 | { 48 | SPDLOG_THROW(spdlog_ex("async flush: thread pool doesn't exist anymore")); 49 | } 50 | } 51 | 52 | // 53 | // backend functions - called from the thread pool to do the actual job 54 | // 55 | SPDLOG_INLINE void spdlog::async_logger::backend_sink_it_(const details::log_msg &msg) 56 | { 57 | for (auto &sink : sinks_) 58 | { 59 | if (sink->should_log(msg.level)) 60 | { 61 | SPDLOG_TRY 62 | { 63 | sink->log(msg); 64 | } 65 | SPDLOG_LOGGER_CATCH() 66 | } 67 | } 68 | 69 | if (should_flush_(msg)) 70 | { 71 | backend_flush_(); 72 | } 73 | } 74 | 75 | SPDLOG_INLINE void spdlog::async_logger::backend_flush_() 76 | { 77 | for (auto &sink : sinks_) 78 | { 79 | SPDLOG_TRY 80 | { 81 | sink->flush(); 82 | } 83 | SPDLOG_LOGGER_CATCH() 84 | } 85 | } 86 | 87 | SPDLOG_INLINE std::shared_ptr spdlog::async_logger::clone(std::string new_name) 88 | { 89 | auto cloned = std::make_shared(*this); 90 | cloned->name_ = std::move(new_name); 91 | return cloned; 92 | } 93 | -------------------------------------------------------------------------------- /utp_common.cpp: -------------------------------------------------------------------------------- 1 | #include "utp_common.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | namespace rtttech_utp 14 | { 15 | 16 | int GetBitmapBits(CircleSeq next_expect, CircleSeq seq_max, int seq_queue_size) 17 | { 18 | if (seq_queue_size == 0) 19 | return 0; 20 | 21 | int bits = uint16_t(seq_max - next_expect); 22 | 23 | return bits; 24 | } 25 | 26 | int GenerateAckBitfield(CircleSeq next_expect, const std::vector>& seqvec, char* bitbuff, int buffsize) 27 | { 28 | memset(bitbuff, 0, buffsize); 29 | 30 | if (seqvec.size() == 0) 31 | return 0; 32 | 33 | assert(seqvec[0] >= next_expect); 34 | 35 | int pos = 0; 36 | for (int i = 0; i < seqvec.size(); ++i) { 37 | pos = uint16_t(seqvec[i] - next_expect -1); 38 | if (pos / 8 < buffsize) 39 | BitmapSet(pos, true, bitbuff, buffsize); 40 | else 41 | break; 42 | } 43 | 44 | return (pos + 8) / 8; 45 | } 46 | 47 | int XorData(const char* data1, int len1, const char* data2, int len2, char* out, int outlen) 48 | { 49 | int ret = std::max(len1, len2); 50 | 51 | if (outlen < ret) 52 | return -1; 53 | 54 | int minlen = std::min(len1, len2); 55 | 56 | for (int i = 0; i < minlen; ++i) { 57 | out[i] = data1[i] ^ data2[i]; 58 | } 59 | 60 | if (len1 < len2) { 61 | memcpy(out + minlen, data2 + minlen, ret - minlen); 62 | } 63 | else if (len2 < len1) { 64 | memcpy(out + minlen, data1 + minlen, ret - minlen); 65 | } 66 | else { 67 | 68 | } 69 | 70 | 71 | return ret; 72 | } 73 | 74 | void BitmapSet(int pos, bool b, char* buff, int len) 75 | { 76 | int nByteIndex = pos / 8; 77 | int nBitIndex = pos % 8; 78 | 79 | uint8_t ch = '\x01'; 80 | ch <<= nBitIndex; 81 | if (b) { 82 | buff[nByteIndex] |= ch; 83 | } 84 | else { 85 | buff[nByteIndex] &= ~ch; 86 | } 87 | } 88 | 89 | bool BitmapGet(int pos, const char* buff, int len) 90 | { 91 | int nByteIndex = pos / 8; 92 | int nBitIndex = pos % 8; 93 | 94 | return (buff[nByteIndex] & (static_cast('\x01') << nBitIndex)) != 0; 95 | } 96 | 97 | std::string Bitmap01String(const char* buff, int len) 98 | { 99 | std::ostringstream oss; 100 | 101 | for (int i = 0; i < len * 8; i++) { 102 | if (BitmapGet(i, buff, len)) { 103 | oss << "1"; 104 | } 105 | else { 106 | oss << "0"; 107 | } 108 | } 109 | 110 | std::string ret = oss.str(); 111 | /*if (ret.size() > 0 && ret[0] != '0') 112 | return ret;*/ 113 | 114 | return ret; 115 | } 116 | 117 | void AssertFailLog(const char *szExpr, const char *szFile, unsigned int nLine) 118 | { 119 | std::cout< 13 | 14 | namespace spdlog { 15 | 16 | namespace sinks { 17 | 18 | template 19 | SPDLOG_INLINE stdout_sink_base::stdout_sink_base(FILE *file) 20 | : mutex_(ConsoleMutex::mutex()) 21 | , file_(file) 22 | , formatter_(details::make_unique()) 23 | {} 24 | 25 | template 26 | SPDLOG_INLINE void stdout_sink_base::log(const details::log_msg &msg) 27 | { 28 | std::lock_guard lock(mutex_); 29 | memory_buf_t formatted; 30 | formatter_->format(msg, formatted); 31 | fwrite(formatted.data(), sizeof(char), formatted.size(), file_); 32 | fflush(file_); // flush every line to terminal 33 | } 34 | 35 | template 36 | SPDLOG_INLINE void stdout_sink_base::flush() 37 | { 38 | std::lock_guard lock(mutex_); 39 | fflush(file_); 40 | } 41 | 42 | template 43 | SPDLOG_INLINE void stdout_sink_base::set_pattern(const std::string &pattern) 44 | { 45 | std::lock_guard lock(mutex_); 46 | formatter_ = std::unique_ptr(new pattern_formatter(pattern)); 47 | } 48 | 49 | template 50 | SPDLOG_INLINE void stdout_sink_base::set_formatter(std::unique_ptr sink_formatter) 51 | { 52 | std::lock_guard lock(mutex_); 53 | formatter_ = std::move(sink_formatter); 54 | } 55 | 56 | // stdout sink 57 | template 58 | SPDLOG_INLINE stdout_sink::stdout_sink() 59 | : stdout_sink_base(stdout) 60 | {} 61 | 62 | // stderr sink 63 | template 64 | SPDLOG_INLINE stderr_sink::stderr_sink() 65 | : stdout_sink_base(stderr) 66 | {} 67 | 68 | } // namespace sinks 69 | 70 | // factory methods 71 | template 72 | SPDLOG_INLINE std::shared_ptr stdout_logger_mt(const std::string &logger_name) 73 | { 74 | return Factory::template create(logger_name); 75 | } 76 | 77 | template 78 | SPDLOG_INLINE std::shared_ptr stdout_logger_st(const std::string &logger_name) 79 | { 80 | return Factory::template create(logger_name); 81 | } 82 | 83 | template 84 | SPDLOG_INLINE std::shared_ptr stderr_logger_mt(const std::string &logger_name) 85 | { 86 | return Factory::template create(logger_name); 87 | } 88 | 89 | template 90 | SPDLOG_INLINE std::shared_ptr stderr_logger_st(const std::string &logger_name) 91 | { 92 | return Factory::template create(logger_name); 93 | } 94 | } // namespace spdlog 95 | -------------------------------------------------------------------------------- /spdlog/details/pattern_formatter.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include "spdlog/common.h" 7 | #include "spdlog/details/log_msg.h" 8 | #include "spdlog/details/os.h" 9 | #include "spdlog/formatter.h" 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | 18 | namespace spdlog { 19 | namespace details { 20 | 21 | // padding information. 22 | struct padding_info 23 | { 24 | enum pad_side 25 | { 26 | left, 27 | right, 28 | center 29 | }; 30 | 31 | padding_info() = default; 32 | padding_info(size_t width, padding_info::pad_side side) 33 | : width_(width) 34 | , side_(side) 35 | {} 36 | 37 | bool enabled() const 38 | { 39 | return width_ != 0; 40 | } 41 | const size_t width_ = 0; 42 | const pad_side side_ = left; 43 | }; 44 | 45 | class flag_formatter 46 | { 47 | public: 48 | explicit flag_formatter(padding_info padinfo) 49 | : padinfo_(padinfo) 50 | {} 51 | flag_formatter() = default; 52 | virtual ~flag_formatter() = default; 53 | virtual void format(const details::log_msg &msg, const std::tm &tm_time, memory_buf_t &dest) = 0; 54 | 55 | protected: 56 | padding_info padinfo_; 57 | }; 58 | 59 | } // namespace details 60 | 61 | class pattern_formatter final : public formatter 62 | { 63 | public: 64 | explicit pattern_formatter( 65 | std::string pattern, pattern_time_type time_type = pattern_time_type::local, std::string eol = spdlog::details::os::default_eol); 66 | 67 | // use default pattern is not given 68 | explicit pattern_formatter(pattern_time_type time_type = pattern_time_type::local, std::string eol = spdlog::details::os::default_eol); 69 | 70 | pattern_formatter(const pattern_formatter &other) = delete; 71 | pattern_formatter &operator=(const pattern_formatter &other) = delete; 72 | 73 | std::unique_ptr clone() const override; 74 | void format(const details::log_msg &msg, memory_buf_t &dest) override; 75 | 76 | private: 77 | std::string pattern_; 78 | std::string eol_; 79 | pattern_time_type pattern_time_type_; 80 | std::tm cached_tm_; 81 | std::chrono::seconds last_log_secs_; 82 | std::vector> formatters_; 83 | 84 | std::tm get_time_(const details::log_msg &msg); 85 | template 86 | void handle_flag_(char flag, details::padding_info padding); 87 | 88 | // Extract given pad spec (e.g. %8X) 89 | // Advance the given it pass the end of the padding spec found (if any) 90 | // Return padding. 91 | details::padding_info handle_padspec_(std::string::const_iterator &it, std::string::const_iterator end); 92 | 93 | void compile_pattern_(const std::string &pattern); 94 | }; 95 | } // namespace spdlog 96 | 97 | #ifdef SPDLOG_HEADER_ONLY 98 | #include "pattern_formatter-inl.h" 99 | #endif 100 | -------------------------------------------------------------------------------- /spdlog/fmt/bundled/locale.h: -------------------------------------------------------------------------------- 1 | // Formatting library for C++ - std::locale support 2 | // 3 | // Copyright (c) 2012 - present, Victor Zverovich 4 | // All rights reserved. 5 | // 6 | // For the license information refer to format.h. 7 | 8 | #ifndef FMT_LOCALE_H_ 9 | #define FMT_LOCALE_H_ 10 | 11 | #include 12 | #include "format.h" 13 | 14 | FMT_BEGIN_NAMESPACE 15 | 16 | namespace internal { 17 | template 18 | typename buffer_context::iterator vformat_to( 19 | const std::locale& loc, buffer& buf, 20 | basic_string_view format_str, 21 | basic_format_args> args) { 22 | using range = buffer_range; 23 | return vformat_to>(buf, to_string_view(format_str), args, 24 | internal::locale_ref(loc)); 25 | } 26 | 27 | template 28 | std::basic_string vformat(const std::locale& loc, 29 | basic_string_view format_str, 30 | basic_format_args> args) { 31 | basic_memory_buffer buffer; 32 | internal::vformat_to(loc, buffer, format_str, args); 33 | return fmt::to_string(buffer); 34 | } 35 | } // namespace internal 36 | 37 | template > 38 | inline std::basic_string vformat( 39 | const std::locale& loc, const S& format_str, 40 | basic_format_args> args) { 41 | return internal::vformat(loc, to_string_view(format_str), args); 42 | } 43 | 44 | template > 45 | inline std::basic_string format(const std::locale& loc, 46 | const S& format_str, Args&&... args) { 47 | return internal::vformat( 48 | loc, to_string_view(format_str), 49 | {internal::make_args_checked(format_str, args...)}); 50 | } 51 | 52 | template ::value, char_t>> 55 | inline OutputIt vformat_to(OutputIt out, const std::locale& loc, 56 | const S& format_str, 57 | format_args_t args) { 58 | using range = internal::output_range; 59 | return vformat_to>( 60 | range(out), to_string_view(format_str), args, internal::locale_ref(loc)); 61 | } 62 | 63 | template ::value&& 65 | internal::is_string::value)> 66 | inline OutputIt format_to(OutputIt out, const std::locale& loc, 67 | const S& format_str, Args&&... args) { 68 | internal::check_format_string(format_str); 69 | using context = format_context_t>; 70 | format_arg_store as{args...}; 71 | return vformat_to(out, loc, to_string_view(format_str), 72 | basic_format_args(as)); 73 | } 74 | 75 | FMT_END_NAMESPACE 76 | 77 | #endif // FMT_LOCALE_H_ 78 | -------------------------------------------------------------------------------- /spdlog/details/os.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include "spdlog/common.h" 7 | #include // std::time_t 8 | 9 | namespace spdlog { 10 | namespace details { 11 | namespace os { 12 | 13 | spdlog::log_clock::time_point now() SPDLOG_NOEXCEPT; 14 | 15 | std::tm localtime(const std::time_t &time_tt) SPDLOG_NOEXCEPT; 16 | 17 | std::tm localtime() SPDLOG_NOEXCEPT; 18 | 19 | std::tm gmtime(const std::time_t &time_tt) SPDLOG_NOEXCEPT; 20 | 21 | std::tm gmtime() SPDLOG_NOEXCEPT; 22 | 23 | // eol definition 24 | #if !defined(SPDLOG_EOL) 25 | #ifdef _WIN32 26 | #define SPDLOG_EOL "\r\n" 27 | #else 28 | #define SPDLOG_EOL "\n" 29 | #endif 30 | #endif 31 | 32 | SPDLOG_CONSTEXPR static const char *default_eol = SPDLOG_EOL; 33 | 34 | // folder separator 35 | #ifdef _WIN32 36 | const char folder_sep = '\\'; 37 | #else 38 | SPDLOG_CONSTEXPR static const char folder_sep = '/'; 39 | #endif 40 | 41 | void prevent_child_fd(FILE *f); 42 | 43 | // fopen_s on non windows for writing 44 | bool fopen_s(FILE **fp, const filename_t &filename, const filename_t &mode); 45 | 46 | // Remove filename. return 0 on success 47 | int remove(const filename_t &filename) SPDLOG_NOEXCEPT; 48 | 49 | // Remove file if exists. return 0 on success 50 | // Note: Non atomic (might return failure to delete if concurrently deleted by other process/thread) 51 | int remove_if_exists(const filename_t &filename) SPDLOG_NOEXCEPT; 52 | 53 | int rename(const filename_t &filename1, const filename_t &filename2) SPDLOG_NOEXCEPT; 54 | 55 | // Return if file exists. 56 | bool file_exists(const filename_t &filename) SPDLOG_NOEXCEPT; 57 | 58 | // Return file size according to open FILE* object 59 | size_t filesize(FILE *f); 60 | 61 | // Return utc offset in minutes or throw spdlog_ex on failure 62 | int utc_minutes_offset(const std::tm &tm = details::os::localtime()); 63 | 64 | // Return current thread id as size_t 65 | // It exists because the std::this_thread::get_id() is much slower(especially 66 | // under VS 2013) 67 | size_t _thread_id() SPDLOG_NOEXCEPT; 68 | 69 | // Return current thread id as size_t (from thread local storage) 70 | size_t thread_id() SPDLOG_NOEXCEPT; 71 | 72 | // This is avoid msvc issue in sleep_for that happens if the clock changes. 73 | // See https://github.com/gabime/spdlog/issues/609 74 | void sleep_for_millis(int milliseconds) SPDLOG_NOEXCEPT; 75 | 76 | std::string filename_to_str(const filename_t &filename); 77 | 78 | int pid() SPDLOG_NOEXCEPT; 79 | 80 | // Determine if the terminal supports colors 81 | // Source: https://github.com/agauniyal/rang/ 82 | bool is_color_terminal() SPDLOG_NOEXCEPT; 83 | 84 | // Detrmine if the terminal attached 85 | // Source: https://github.com/agauniyal/rang/ 86 | bool in_terminal(FILE *file) SPDLOG_NOEXCEPT; 87 | 88 | #if (defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) || defined(SPDLOG_WCHAR_FILENAMES)) && defined(_WIN32) 89 | void wstr_to_utf8buf(wstring_view_t wstr, memory_buf_t &target); 90 | #endif 91 | 92 | } // namespace os 93 | } // namespace details 94 | } // namespace spdlog 95 | 96 | #ifdef SPDLOG_HEADER_ONLY 97 | #include "os-inl.h" 98 | #endif 99 | -------------------------------------------------------------------------------- /spdlog/sinks/dup_filter_sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include "dist_sink.h" 7 | #include "spdlog/details/null_mutex.h" 8 | #include "spdlog/details/log_msg.h" 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | // Duplicate message removal sink. 15 | // Skip the message if previous one is identical and less than "max_skip_duration" have passed 16 | // 17 | // Example: 18 | // 19 | // #include "spdlog/sinks/dup_filter_sink.h" 20 | // 21 | // int main() { 22 | // auto dup_filter = std::make_shared(std::chrono::seconds(5)); 23 | // dup_filter->add_sink(std::make_shared()); 24 | // spdlog::logger l("logger", dup_filter); 25 | // l.info("Hello"); 26 | // l.info("Hello"); 27 | // l.info("Hello"); 28 | // l.info("Different Hello"); 29 | // } 30 | // 31 | // Will produce: 32 | // [2019-06-25 17:50:56.511] [logger] [info] Hello 33 | // [2019-06-25 17:50:56.512] [logger] [info] Skipped 3 duplicate messages.. 34 | // [2019-06-25 17:50:56.512] [logger] [info] Different Hello 35 | 36 | #ifdef SPDLOG_NO_DATETIME 37 | #error "spdlog::sinks::dup_filter_sink: cannot work when SPDLOG_NO_DATETIME is defined" 38 | #endif 39 | 40 | namespace spdlog { 41 | namespace sinks { 42 | template 43 | class dup_filter_sink : public dist_sink 44 | { 45 | public: 46 | template 47 | explicit dup_filter_sink(std::chrono::duration max_skip_duration) 48 | : max_skip_duration_{max_skip_duration} 49 | {} 50 | 51 | protected: 52 | std::chrono::microseconds max_skip_duration_; 53 | log_clock::time_point last_msg_time_; 54 | std::string last_msg_payload_; 55 | size_t skip_counter_ = 0; 56 | 57 | void sink_it_(const details::log_msg &msg) override 58 | { 59 | bool filtered = filter_(msg); 60 | if (!filtered) 61 | { 62 | skip_counter_ += 1; 63 | return; 64 | } 65 | 66 | // log the "skipped.." message 67 | if (skip_counter_ > 0) 68 | { 69 | memory_buf_t buf; 70 | fmt::format_to(buf, "Skipped {} duplicate messages..", skip_counter_); 71 | details::log_msg skipped_msg{msg.logger_name, msg.level, string_view_t{buf.data(), buf.size()}}; 72 | dist_sink::sink_it_(skipped_msg); 73 | } 74 | 75 | // log current message 76 | dist_sink::sink_it_(msg); 77 | last_msg_time_ = msg.time; 78 | skip_counter_ = 0; 79 | last_msg_payload_.assign(msg.payload.data(), msg.payload.data() + msg.payload.size()); 80 | } 81 | 82 | // return whether the log msg should be displayed (true) or skipped (false) 83 | bool filter_(const details::log_msg &msg) 84 | { 85 | auto filter_duration = msg.time - last_msg_time_; 86 | return (filter_duration > max_skip_duration_) || (msg.payload != last_msg_payload_); 87 | } 88 | }; 89 | 90 | using dup_filter_sink_mt = dup_filter_sink; 91 | using dup_filter_sink_st = dup_filter_sink; 92 | 93 | } // namespace sinks 94 | } // namespace spdlog 95 | -------------------------------------------------------------------------------- /spdlog/sinks/wincolor_sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include "spdlog/common.h" 7 | #include "spdlog/details/console_globals.h" 8 | #include "spdlog/details/null_mutex.h" 9 | #include "spdlog/sinks/sink.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | namespace spdlog { 18 | namespace sinks { 19 | /* 20 | * Windows color console sink. Uses WriteConsoleA to write to the console with 21 | * colors 22 | */ 23 | template 24 | class wincolor_sink : public sink 25 | { 26 | public: 27 | const WORD BOLD = FOREGROUND_INTENSITY; 28 | const WORD RED = FOREGROUND_RED; 29 | const WORD GREEN = FOREGROUND_GREEN; 30 | const WORD CYAN = FOREGROUND_GREEN | FOREGROUND_BLUE; 31 | const WORD WHITE = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; 32 | const WORD YELLOW = FOREGROUND_RED | FOREGROUND_GREEN; 33 | 34 | wincolor_sink(HANDLE out_handle, color_mode mode); 35 | ~wincolor_sink() override; 36 | 37 | wincolor_sink(const wincolor_sink &other) = delete; 38 | wincolor_sink &operator=(const wincolor_sink &other) = delete; 39 | 40 | // change the color for the given level 41 | void set_color(level::level_enum level, WORD color); 42 | void log(const details::log_msg &msg) final override; 43 | void flush() final override; 44 | void set_pattern(const std::string &pattern) override final; 45 | void set_formatter(std::unique_ptr sink_formatter) override final; 46 | void set_color_mode(color_mode mode); 47 | 48 | protected: 49 | using mutex_t = typename ConsoleMutex::mutex_t; 50 | HANDLE out_handle_; 51 | mutex_t &mutex_; 52 | bool in_console_; 53 | bool should_do_colors_; 54 | std::unique_ptr formatter_; 55 | std::unordered_map colors_; 56 | 57 | // set foreground color and return the orig console attributes (for resetting later) 58 | WORD set_foreground_color_(WORD attribs); 59 | 60 | // print a range of formatted message to console 61 | void print_range_(const memory_buf_t &formatted, size_t start, size_t end); 62 | 63 | // in case we are redirected to file (not in console mode) 64 | void write_to_file_(const memory_buf_t &formatted); 65 | }; 66 | 67 | template 68 | class wincolor_stdout_sink : public wincolor_sink 69 | { 70 | public: 71 | explicit wincolor_stdout_sink(color_mode mode = color_mode::automatic); 72 | }; 73 | 74 | template 75 | class wincolor_stderr_sink : public wincolor_sink 76 | { 77 | public: 78 | explicit wincolor_stderr_sink(color_mode mode = color_mode::automatic); 79 | }; 80 | 81 | using wincolor_stdout_sink_mt = wincolor_stdout_sink; 82 | using wincolor_stdout_sink_st = wincolor_stdout_sink; 83 | 84 | using wincolor_stderr_sink_mt = wincolor_stderr_sink; 85 | using wincolor_stderr_sink_st = wincolor_stderr_sink; 86 | 87 | } // namespace sinks 88 | } // namespace spdlog 89 | 90 | #ifdef SPDLOG_HEADER_ONLY 91 | #include "wincolor_sink-inl.h" 92 | #endif 93 | -------------------------------------------------------------------------------- /congestion_control.h: -------------------------------------------------------------------------------- 1 | #ifndef __CONGESTION_CONTROL_H__ 2 | #define __CONGESTION_CONTROL_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "trip_time_sample.h" 9 | #include "log_helper.h" 10 | 11 | const int MAX_WND_SIZE = 16 * 1024 * 1024; 12 | 13 | class CongestionController 14 | { 15 | public: 16 | virtual void OnPacketLost(int64_t time) = 0; 17 | virtual void OnPacketAcked(int64_t time, int64_t rtt) = 0; 18 | virtual void OnPacketTripTime(int64_t time, int64_t tt, int64_t rtt, int64_t nOnFlightPacket) = 0; 19 | 20 | virtual uint32_t GetCongestionWnd() = 0; 21 | virtual ~CongestionController() {} 22 | }; 23 | 24 | class NullCongestionController : public CongestionController 25 | { 26 | public: 27 | NullCongestionController(uint32_t nInitWnd) : m_nWnd(nInitWnd) {} 28 | virtual ~NullCongestionController() {} 29 | 30 | virtual void OnPacketLost(int64_t time) {} 31 | virtual void OnPacketAcked(int64_t time, int64_t rtt) {} 32 | virtual void OnPacketTripTime(int64_t time, int64_t tt, int64_t rtt, int64_t nOnFlightPacket) {} 33 | virtual uint32_t GetCongestionWnd() 34 | { 35 | return m_nWnd; 36 | } 37 | private: 38 | uint32_t m_nWnd; 39 | }; 40 | 41 | 42 | class LedbatCongestionController : public CongestionController 43 | { 44 | public: 45 | const uint32_t MAX_CWND_INCREASE_BYTES_PER_RTT = 3000; 46 | 47 | LedbatCongestionController(uint32_t nMTU, uint32_t nInitWnd, uint32_t nTarget = 100*1000/*, std::shared_ptr ptrLogger = nullptr*/) 48 | : m_nMTU(nMTU), m_nWnd(nInitWnd), m_nControlTarget(nTarget), m_nLastDoLedbat(0)/*, m_ptrLogger(ptrLogger)*/ 49 | { 50 | 51 | } 52 | virtual ~LedbatCongestionController() {} 53 | 54 | virtual void OnPacketLost(int64_t time) 55 | { 56 | 57 | } 58 | virtual void OnPacketAcked(int64_t time, int64_t rtt) 59 | { 60 | 61 | } 62 | 63 | virtual void OnPacketTripTime(int64_t time, int64_t tt, int64_t rtt, int64_t nOnFlightBytes) 64 | { 65 | if (tt < 0 || tt > 6 * 1000 * 1000) 66 | return; 67 | 68 | 69 | int64_t nOffTarget = m_nControlTarget - tt; 70 | 71 | double dbDelayFactor = 1.0*nOffTarget / m_nControlTarget; 72 | //double dbWindowFactor = 1.0*nOnFlightBytes / m_nWnd; 73 | 74 | double dbWindowFactor = 1.0; 75 | 76 | if (rtt == 0) { 77 | rtt = 3 * 1000 * 1000; 78 | } 79 | 80 | int64_t nTimeElapse = rtt; 81 | if (m_nLastDoLedbat != 0) { 82 | nTimeElapse = time - m_nLastDoLedbat; 83 | } 84 | 85 | m_nLastDoLedbat = time; 86 | 87 | double dbScaledGain = MAX_CWND_INCREASE_BYTES_PER_RTT * dbDelayFactor * dbWindowFactor * nTimeElapse / rtt; 88 | 89 | //LOG_DEBUG(m_ptrLogger, "tt:{}, rtt:{}, onflightbytes:{} dbDelayFactor:{}, dbWindowFactor:{}, dbScaledGain:{}, m_nWnd:{}", 90 | // tt, rtt, nOnFlightBytes, dbDelayFactor, dbWindowFactor, dbScaledGain, m_nWnd); 91 | 92 | m_nWnd += dbScaledGain; 93 | 94 | 95 | if (m_nWnd < m_nMTU) { 96 | m_nWnd = m_nMTU; 97 | } 98 | 99 | if (m_nWnd > MAX_WND_SIZE) { 100 | m_nWnd = MAX_WND_SIZE; 101 | } 102 | } 103 | 104 | virtual uint32_t GetCongestionWnd() 105 | { 106 | return m_nWnd; 107 | } 108 | private: 109 | int64_t m_nWnd; 110 | uint32_t m_nMTU; 111 | int64_t m_nControlTarget; 112 | int64_t m_nLastDoLedbat; 113 | 114 | //std::shared_ptr m_ptrLogger; 115 | }; 116 | 117 | 118 | #endif 119 | -------------------------------------------------------------------------------- /spdlog/details/fmt_helper.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include "spdlog/fmt/fmt.h" 8 | #include "spdlog/common.h" 9 | 10 | // Some fmt helpers to efficiently format and pad ints and strings 11 | namespace spdlog { 12 | namespace details { 13 | namespace fmt_helper { 14 | 15 | inline spdlog::string_view_t to_string_view(const memory_buf_t &buf) SPDLOG_NOEXCEPT 16 | { 17 | return spdlog::string_view_t{buf.data(), buf.size()}; 18 | } 19 | 20 | inline void append_string_view(spdlog::string_view_t view, memory_buf_t &dest) 21 | { 22 | auto *buf_ptr = view.data(); 23 | if (buf_ptr != nullptr) 24 | { 25 | dest.append(buf_ptr, buf_ptr + view.size()); 26 | } 27 | } 28 | 29 | template 30 | inline void append_int(T n, memory_buf_t &dest) 31 | { 32 | fmt::format_int i(n); 33 | dest.append(i.data(), i.data() + i.size()); 34 | } 35 | 36 | template 37 | inline unsigned count_digits(T n) 38 | { 39 | using count_type = typename std::conditional<(sizeof(T) > sizeof(uint32_t)), uint64_t, uint32_t>::type; 40 | return static_cast(fmt::internal::count_digits(static_cast(n))); 41 | } 42 | 43 | inline void pad2(int n, memory_buf_t &dest) 44 | { 45 | if (n > 99) 46 | { 47 | append_int(n, dest); 48 | } 49 | else if (n > 9) // 10-99 50 | { 51 | dest.push_back(static_cast('0' + n / 10)); 52 | dest.push_back(static_cast('0' + n % 10)); 53 | } 54 | else if (n >= 0) // 0-9 55 | { 56 | dest.push_back('0'); 57 | dest.push_back(static_cast('0' + n)); 58 | } 59 | else // negatives (unlikely, but just in case, let fmt deal with it) 60 | { 61 | fmt::format_to(dest, "{:02}", n); 62 | } 63 | } 64 | 65 | template 66 | inline void pad_uint(T n, unsigned int width, memory_buf_t &dest) 67 | { 68 | static_assert(std::is_unsigned::value, "pad_uint must get unsigned T"); 69 | auto digits = count_digits(n); 70 | if (width > digits) 71 | { 72 | const char *zeroes = "0000000000000000000"; 73 | dest.append(zeroes, zeroes + width - digits); 74 | } 75 | append_int(n, dest); 76 | } 77 | 78 | template 79 | inline void pad3(T n, memory_buf_t &dest) 80 | { 81 | pad_uint(n, 3, dest); 82 | } 83 | 84 | template 85 | inline void pad6(T n, memory_buf_t &dest) 86 | { 87 | pad_uint(n, 6, dest); 88 | } 89 | 90 | template 91 | inline void pad9(T n, memory_buf_t &dest) 92 | { 93 | pad_uint(n, 9, dest); 94 | } 95 | 96 | // return fraction of a second of the given time_point. 97 | // e.g. 98 | // fraction(tp) -> will return the millis part of the second 99 | template 100 | inline ToDuration time_fraction(log_clock::time_point tp) 101 | { 102 | using std::chrono::duration_cast; 103 | using std::chrono::seconds; 104 | auto duration = tp.time_since_epoch(); 105 | auto secs = duration_cast(duration); 106 | return duration_cast(duration) - duration_cast(secs); 107 | } 108 | 109 | } // namespace fmt_helper 110 | } // namespace details 111 | } // namespace spdlog 112 | -------------------------------------------------------------------------------- /spdlog/spdlog-inl.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifndef SPDLOG_HEADER_ONLY 7 | #include "spdlog/spdlog.h" 8 | #endif 9 | 10 | #include "spdlog/common.h" 11 | #include "spdlog/details/pattern_formatter.h" 12 | 13 | namespace spdlog { 14 | 15 | SPDLOG_INLINE void initialize_logger(std::shared_ptr logger) 16 | { 17 | details::registry::instance().initialize_logger(std::move(logger)); 18 | } 19 | 20 | SPDLOG_INLINE std::shared_ptr get(const std::string &name) 21 | { 22 | return details::registry::instance().get(name); 23 | } 24 | 25 | SPDLOG_INLINE void set_formatter(std::unique_ptr formatter) 26 | { 27 | details::registry::instance().set_formatter(std::move(formatter)); 28 | } 29 | 30 | SPDLOG_INLINE void set_pattern(std::string pattern, pattern_time_type time_type) 31 | { 32 | set_formatter(std::unique_ptr(new pattern_formatter(std::move(pattern), time_type))); 33 | } 34 | 35 | SPDLOG_INLINE void enable_backtrace(size_t n_messages) 36 | { 37 | details::registry::instance().enable_backtrace(n_messages); 38 | } 39 | 40 | SPDLOG_INLINE void disable_backtrace() 41 | { 42 | details::registry::instance().disable_backtrace(); 43 | } 44 | 45 | SPDLOG_INLINE void dump_backtrace() 46 | { 47 | default_logger_raw()->dump_backtrace(); 48 | } 49 | 50 | SPDLOG_INLINE void set_level(level::level_enum log_level) 51 | { 52 | details::registry::instance().set_level(log_level); 53 | } 54 | 55 | SPDLOG_INLINE void flush_on(level::level_enum log_level) 56 | { 57 | details::registry::instance().flush_on(log_level); 58 | } 59 | 60 | SPDLOG_INLINE void flush_every(std::chrono::seconds interval) 61 | { 62 | details::registry::instance().flush_every(interval); 63 | } 64 | 65 | SPDLOG_INLINE void set_error_handler(void (*handler)(const std::string &msg)) 66 | { 67 | details::registry::instance().set_error_handler(handler); 68 | } 69 | 70 | SPDLOG_INLINE void register_logger(std::shared_ptr logger) 71 | { 72 | details::registry::instance().register_logger(std::move(logger)); 73 | } 74 | 75 | SPDLOG_INLINE void apply_all(const std::function)> &fun) 76 | { 77 | details::registry::instance().apply_all(fun); 78 | } 79 | 80 | SPDLOG_INLINE void drop(const std::string &name) 81 | { 82 | details::registry::instance().drop(name); 83 | } 84 | 85 | SPDLOG_INLINE void drop_all() 86 | { 87 | details::registry::instance().drop_all(); 88 | } 89 | 90 | SPDLOG_INLINE void shutdown() 91 | { 92 | details::registry::instance().shutdown(); 93 | } 94 | 95 | SPDLOG_INLINE void set_automatic_registration(bool automatic_registation) 96 | { 97 | details::registry::instance().set_automatic_registration(automatic_registation); 98 | } 99 | 100 | SPDLOG_INLINE std::shared_ptr default_logger() 101 | { 102 | return details::registry::instance().default_logger(); 103 | } 104 | 105 | SPDLOG_INLINE spdlog::logger *default_logger_raw() 106 | { 107 | return details::registry::instance().get_default_raw(); 108 | } 109 | 110 | SPDLOG_INLINE void set_default_logger(std::shared_ptr default_logger) 111 | { 112 | details::registry::instance().set_default_logger(std::move(default_logger)); 113 | } 114 | 115 | } // namespace spdlog -------------------------------------------------------------------------------- /spdlog/sinks/systemd_sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2019 ZVYAGIN.Alexander@gmail.com 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include "spdlog/sinks/base_sink.h" 7 | #include "spdlog/details/null_mutex.h" 8 | #include "spdlog/details/synchronous_factory.h" 9 | 10 | #include 11 | 12 | namespace spdlog { 13 | namespace sinks { 14 | 15 | /** 16 | * Sink that write to systemd journal using the `sd_journal_send()` library call. 17 | * 18 | * Locking is not needed, as `sd_journal_send()` itself is thread-safe. 19 | */ 20 | template 21 | class systemd_sink : public base_sink 22 | { 23 | public: 24 | // 25 | systemd_sink() 26 | : syslog_levels_{{/* spdlog::level::trace */ LOG_DEBUG, 27 | /* spdlog::level::debug */ LOG_DEBUG, 28 | /* spdlog::level::info */ LOG_INFO, 29 | /* spdlog::level::warn */ LOG_WARNING, 30 | /* spdlog::level::err */ LOG_ERR, 31 | /* spdlog::level::critical */ LOG_CRIT, 32 | /* spdlog::level::off */ LOG_INFO}} 33 | {} 34 | 35 | ~systemd_sink() override {} 36 | 37 | systemd_sink(const systemd_sink &) = delete; 38 | systemd_sink &operator=(const systemd_sink &) = delete; 39 | 40 | protected: 41 | using levels_array = std::array; 42 | levels_array syslog_levels_; 43 | 44 | void sink_it_(const details::log_msg &msg) override 45 | { 46 | int err; 47 | 48 | size_t length = msg.payload.size(); 49 | // limit to max int 50 | if (length > static_cast(std::numeric_limits::max())) 51 | { 52 | length = static_cast(std::numeric_limits::max()); 53 | } 54 | 55 | // Do not send source location if not available 56 | if (msg.source.empty()) 57 | { 58 | // Note: function call inside '()' to avoid macro expansion 59 | err = (sd_journal_send)( 60 | "MESSAGE=%.*s", static_cast(length), msg.payload.data(), "PRIORITY=%d", syslog_level(msg.level), nullptr); 61 | } 62 | else 63 | { 64 | err = (sd_journal_send)("MESSAGE=%.*s", static_cast(length), msg.payload.data(), "PRIORITY=%d", syslog_level(msg.level), 65 | "SOURCE_FILE=%s", msg.source.filename, "SOURCE_LINE=%d", msg.source.line, "SOURCE_FUNC=%s", msg.source.funcname, nullptr); 66 | } 67 | 68 | if (err) 69 | { 70 | SPDLOG_THROW(spdlog_ex("Failed writing to systemd", errno)); 71 | } 72 | } 73 | 74 | int syslog_level(level::level_enum l) 75 | { 76 | return syslog_levels_.at(static_cast(l)); 77 | } 78 | 79 | void flush_() override {} 80 | }; 81 | 82 | using systemd_sink_mt = systemd_sink; 83 | using systemd_sink_st = systemd_sink; 84 | } // namespace sinks 85 | 86 | // Create and register a syslog logger 87 | template 88 | inline std::shared_ptr systemd_logger_mt(const std::string &logger_name) 89 | { 90 | return Factory::template create(logger_name); 91 | } 92 | 93 | template 94 | inline std::shared_ptr systemd_logger_st(const std::string &logger_name) 95 | { 96 | return Factory::template create(logger_name); 97 | } 98 | } // namespace spdlog 99 | -------------------------------------------------------------------------------- /spdlog/details/circular_q.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | // cirucal q view of std::vector. 5 | #pragma once 6 | 7 | #include 8 | 9 | namespace spdlog { 10 | namespace details { 11 | template 12 | class circular_q 13 | { 14 | size_t max_items_ = 0; 15 | typename std::vector::size_type head_ = 0; 16 | typename std::vector::size_type tail_ = 0; 17 | size_t overrun_counter_ = 0; 18 | std::vector v_; 19 | 20 | public: 21 | using value_type = T; 22 | 23 | // empty ctor - create a disabled queue with no elements allocated at all 24 | circular_q() = default; 25 | 26 | explicit circular_q(size_t max_items) 27 | : max_items_(max_items + 1) // one item is reserved as marker for full q 28 | , v_(max_items_) 29 | {} 30 | 31 | circular_q(const circular_q &) = default; 32 | circular_q &operator=(const circular_q &) = default; 33 | 34 | // move cannot be default, 35 | // since we need to reset head_, tail_, etc to zero in the moved object 36 | circular_q(circular_q &&other) SPDLOG_NOEXCEPT 37 | { 38 | copy_moveable(std::move(other)); 39 | } 40 | 41 | circular_q &operator=(circular_q &&other) SPDLOG_NOEXCEPT 42 | { 43 | copy_moveable(std::move(other)); 44 | return *this; 45 | } 46 | 47 | // push back, overrun (oldest) item if no room left 48 | void push_back(T &&item) 49 | { 50 | if (max_items_ > 0) 51 | { 52 | v_[tail_] = std::move(item); 53 | tail_ = (tail_ + 1) % max_items_; 54 | 55 | if (tail_ == head_) // overrun last item if full 56 | { 57 | head_ = (head_ + 1) % max_items_; 58 | ++overrun_counter_; 59 | } 60 | } 61 | } 62 | 63 | // Return reference to the front item. 64 | // If there are no elements in the container, the behavior is undefined. 65 | const T &front() const 66 | { 67 | return v_[head_]; 68 | } 69 | 70 | T &front() 71 | { 72 | return v_[head_]; 73 | } 74 | 75 | // Pop item from front. 76 | // If there are no elements in the container, the behavior is undefined. 77 | void pop_front() 78 | { 79 | head_ = (head_ + 1) % max_items_; 80 | } 81 | 82 | bool empty() const 83 | { 84 | return tail_ == head_; 85 | } 86 | 87 | bool full() const 88 | { 89 | // head is ahead of the tail by 1 90 | if (max_items_ > 0) 91 | { 92 | return ((tail_ + 1) % max_items_) == head_; 93 | } 94 | return false; 95 | } 96 | 97 | size_t overrun_counter() const 98 | { 99 | return overrun_counter_; 100 | } 101 | 102 | private: 103 | // copy from other&& and reset it to disabled state 104 | void copy_moveable(circular_q &&other) SPDLOG_NOEXCEPT 105 | { 106 | max_items_ = other.max_items_; 107 | head_ = other.head_; 108 | tail_ = other.tail_; 109 | overrun_counter_ = other.overrun_counter_; 110 | v_ = std::move(other.v_); 111 | 112 | // put &&other in disabled, but valid state 113 | other.max_items_ = 0; 114 | other.head_ = other.tail_ = 0; 115 | other.overrun_counter_ = 0; 116 | } 117 | }; 118 | } // namespace details 119 | } // namespace spdlog 120 | -------------------------------------------------------------------------------- /spdlog/async.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | // 7 | // Async logging using global thread pool 8 | // All loggers created here share same global thread pool. 9 | // Each log message is pushed to a queue along withe a shared pointer to the 10 | // logger. 11 | // If a logger deleted while having pending messages in the queue, it's actual 12 | // destruction will defer 13 | // until all its messages are processed by the thread pool. 14 | // This is because each message in the queue holds a shared_ptr to the 15 | // originating logger. 16 | 17 | #include "spdlog/async_logger.h" 18 | #include "spdlog/details/registry.h" 19 | #include "spdlog/details/thread_pool.h" 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | namespace spdlog { 26 | 27 | namespace details { 28 | static const size_t default_async_q_size = 8192; 29 | } 30 | 31 | // async logger factory - creates async loggers backed with thread pool. 32 | // if a global thread pool doesn't already exist, create it with default queue 33 | // size of 8192 items and single thread. 34 | template 35 | struct async_factory_impl 36 | { 37 | template 38 | static std::shared_ptr create(std::string logger_name, SinkArgs &&... args) 39 | { 40 | auto ®istry_inst = details::registry::instance(); 41 | 42 | // create global thread pool if not already exists.. 43 | 44 | auto &mutex = registry_inst.tp_mutex(); 45 | std::lock_guard tp_lock(mutex); 46 | auto tp = registry_inst.get_tp(); 47 | if (tp == nullptr) 48 | { 49 | tp = std::make_shared(details::default_async_q_size, 1); 50 | registry_inst.set_tp(tp); 51 | } 52 | 53 | auto sink = std::make_shared(std::forward(args)...); 54 | auto new_logger = std::make_shared(std::move(logger_name), std::move(sink), std::move(tp), OverflowPolicy); 55 | registry_inst.initialize_logger(new_logger); 56 | return new_logger; 57 | } 58 | }; 59 | 60 | using async_factory = async_factory_impl; 61 | using async_factory_nonblock = async_factory_impl; 62 | 63 | template 64 | inline std::shared_ptr create_async(std::string logger_name, SinkArgs &&... sink_args) 65 | { 66 | return async_factory::create(std::move(logger_name), std::forward(sink_args)...); 67 | } 68 | 69 | template 70 | inline std::shared_ptr create_async_nb(std::string logger_name, SinkArgs &&... sink_args) 71 | { 72 | return async_factory_nonblock::create(std::move(logger_name), std::forward(sink_args)...); 73 | } 74 | 75 | // set global thread pool. 76 | inline void init_thread_pool(size_t q_size, size_t thread_count, std::function on_thread_start) 77 | { 78 | auto tp = std::make_shared(q_size, thread_count, on_thread_start); 79 | details::registry::instance().set_tp(std::move(tp)); 80 | } 81 | 82 | // set global thread pool. 83 | inline void init_thread_pool(size_t q_size, size_t thread_count) 84 | { 85 | init_thread_pool(q_size, thread_count, [] {}); 86 | } 87 | 88 | // get the global thread pool. 89 | inline std::shared_ptr thread_pool() 90 | { 91 | return details::registry::instance().get_tp(); 92 | } 93 | } // namespace spdlog 94 | -------------------------------------------------------------------------------- /spdlog/details/thread_pool.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include "spdlog/details/log_msg_buffer.h" 7 | #include "spdlog/details/mpmc_blocking_q.h" 8 | #include "spdlog/details/os.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | namespace spdlog { 17 | class async_logger; 18 | 19 | namespace details { 20 | 21 | using async_logger_ptr = std::shared_ptr; 22 | 23 | enum class async_msg_type 24 | { 25 | log, 26 | flush, 27 | terminate 28 | }; 29 | 30 | #include "spdlog/details/log_msg_buffer.h" 31 | // Async msg to move to/from the queue 32 | // Movable only. should never be copied 33 | struct async_msg : log_msg_buffer 34 | { 35 | async_msg_type msg_type{async_msg_type::log}; 36 | async_logger_ptr worker_ptr; 37 | 38 | async_msg() = default; 39 | ~async_msg() = default; 40 | 41 | // should only be moved in or out of the queue.. 42 | async_msg(const async_msg &) = delete; 43 | 44 | // support for vs2013 move 45 | #if defined(_MSC_VER) && _MSC_VER <= 1800 46 | async_msg(async_msg &&other) 47 | : log_msg_buffer(std::move(other)) 48 | , msg_type(other.msg_type) 49 | , worker_ptr(std::move(other.worker_ptr)) 50 | {} 51 | 52 | async_msg &operator=(async_msg &&other) 53 | { 54 | *static_cast(this) = std::move(other); 55 | msg_type = other.msg_type; 56 | worker_ptr = std::move(other.worker_ptr); 57 | return *this; 58 | } 59 | #else // (_MSC_VER) && _MSC_VER <= 1800 60 | async_msg(async_msg &&) = default; 61 | async_msg &operator=(async_msg &&) = default; 62 | #endif 63 | 64 | // construct from log_msg with given type 65 | async_msg(async_logger_ptr &&worker, async_msg_type the_type, const details::log_msg &m) 66 | : log_msg_buffer{m} 67 | , msg_type{the_type} 68 | , worker_ptr{std::move(worker)} 69 | {} 70 | 71 | async_msg(async_logger_ptr &&worker, async_msg_type the_type) 72 | : log_msg_buffer{} 73 | , msg_type{the_type} 74 | , worker_ptr{std::move(worker)} 75 | {} 76 | 77 | explicit async_msg(async_msg_type the_type) 78 | : async_msg{nullptr, the_type} 79 | {} 80 | }; 81 | 82 | class thread_pool 83 | { 84 | public: 85 | using item_type = async_msg; 86 | using q_type = details::mpmc_blocking_queue; 87 | 88 | thread_pool(size_t q_max_items, size_t threads_n, std::function on_thread_start); 89 | thread_pool(size_t q_max_items, size_t threads_n); 90 | 91 | // message all threads to terminate gracefully join them 92 | ~thread_pool(); 93 | 94 | thread_pool(const thread_pool &) = delete; 95 | thread_pool &operator=(thread_pool &&) = delete; 96 | 97 | void post_log(async_logger_ptr &&worker_ptr, const details::log_msg &msg, async_overflow_policy overflow_policy); 98 | void post_flush(async_logger_ptr &&worker_ptr, async_overflow_policy overflow_policy); 99 | size_t overrun_counter(); 100 | 101 | private: 102 | q_type q_; 103 | 104 | std::vector threads_; 105 | 106 | void post_async_msg_(async_msg &&new_msg, async_overflow_policy overflow_policy); 107 | void worker_loop_(); 108 | 109 | // process next message in the queue 110 | // return true if this thread should still be active (while no terminate msg 111 | // was received) 112 | bool process_next_msg_(); 113 | }; 114 | 115 | } // namespace details 116 | } // namespace spdlog 117 | 118 | #ifdef SPDLOG_HEADER_ONLY 119 | #include "thread_pool-inl.h" 120 | #endif 121 | -------------------------------------------------------------------------------- /spdlog/details/thread_pool-inl.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifndef SPDLOG_HEADER_ONLY 7 | #include "spdlog/details/thread_pool.h" 8 | #endif 9 | 10 | #include "spdlog/common.h" 11 | 12 | namespace spdlog { 13 | namespace details { 14 | 15 | SPDLOG_INLINE thread_pool::thread_pool(size_t q_max_items, size_t threads_n, std::function on_thread_start) 16 | : q_(q_max_items) 17 | { 18 | if (threads_n == 0 || threads_n > 1000) 19 | { 20 | SPDLOG_THROW(spdlog_ex("spdlog::thread_pool(): invalid threads_n param (valid " 21 | "range is 1-1000)")); 22 | } 23 | for (size_t i = 0; i < threads_n; i++) 24 | { 25 | threads_.emplace_back([this, on_thread_start] { 26 | on_thread_start(); 27 | this->thread_pool::worker_loop_(); 28 | }); 29 | } 30 | } 31 | 32 | SPDLOG_INLINE thread_pool::thread_pool(size_t q_max_items, size_t threads_n) 33 | : thread_pool(q_max_items, threads_n, [] {}) 34 | {} 35 | 36 | // message all threads to terminate gracefully join them 37 | SPDLOG_INLINE thread_pool::~thread_pool() 38 | { 39 | SPDLOG_TRY 40 | { 41 | for (size_t i = 0; i < threads_.size(); i++) 42 | { 43 | post_async_msg_(async_msg(async_msg_type::terminate), async_overflow_policy::block); 44 | } 45 | 46 | for (auto &t : threads_) 47 | { 48 | t.join(); 49 | } 50 | } 51 | SPDLOG_CATCH_ALL() {} 52 | } 53 | 54 | void SPDLOG_INLINE thread_pool::post_log(async_logger_ptr &&worker_ptr, const details::log_msg &msg, async_overflow_policy overflow_policy) 55 | { 56 | async_msg async_m(std::move(worker_ptr), async_msg_type::log, msg); 57 | post_async_msg_(std::move(async_m), overflow_policy); 58 | } 59 | 60 | void SPDLOG_INLINE thread_pool::post_flush(async_logger_ptr &&worker_ptr, async_overflow_policy overflow_policy) 61 | { 62 | post_async_msg_(async_msg(std::move(worker_ptr), async_msg_type::flush), overflow_policy); 63 | } 64 | 65 | size_t SPDLOG_INLINE thread_pool::overrun_counter() 66 | { 67 | return q_.overrun_counter(); 68 | } 69 | 70 | void SPDLOG_INLINE thread_pool::post_async_msg_(async_msg &&new_msg, async_overflow_policy overflow_policy) 71 | { 72 | if (overflow_policy == async_overflow_policy::block) 73 | { 74 | q_.enqueue(std::move(new_msg)); 75 | } 76 | else 77 | { 78 | q_.enqueue_nowait(std::move(new_msg)); 79 | } 80 | } 81 | 82 | void SPDLOG_INLINE thread_pool::worker_loop_() 83 | { 84 | while (process_next_msg_()) {}; 85 | } 86 | 87 | // process next message in the queue 88 | // return true if this thread should still be active (while no terminate msg 89 | // was received) 90 | bool SPDLOG_INLINE thread_pool::process_next_msg_() 91 | { 92 | async_msg incoming_async_msg; 93 | bool dequeued = q_.dequeue_for(incoming_async_msg, std::chrono::seconds(10)); 94 | if (!dequeued) 95 | { 96 | return true; 97 | } 98 | 99 | switch (incoming_async_msg.msg_type) 100 | { 101 | case async_msg_type::log: 102 | { 103 | incoming_async_msg.worker_ptr->backend_sink_it_(incoming_async_msg); 104 | return true; 105 | } 106 | case async_msg_type::flush: 107 | { 108 | incoming_async_msg.worker_ptr->backend_flush_(); 109 | return true; 110 | } 111 | 112 | case async_msg_type::terminate: 113 | { 114 | return false; 115 | } 116 | 117 | default: 118 | { 119 | assert(false && "Unexpected async_msg_type"); 120 | } 121 | } 122 | 123 | return true; 124 | } 125 | 126 | } // namespace details 127 | } // namespace spdlog 128 | -------------------------------------------------------------------------------- /spdlog/details/registry.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | // Loggers registry of unique name->logger pointer 7 | // An attempt to create a logger with an already existing name will result with spdlog_ex exception. 8 | // If user requests a non existing logger, nullptr will be returned 9 | // This class is thread safe 10 | 11 | #include "spdlog/common.h" 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | namespace spdlog { 21 | class logger; 22 | 23 | namespace details { 24 | class thread_pool; 25 | class periodic_worker; 26 | 27 | class registry 28 | { 29 | public: 30 | registry(const registry &) = delete; 31 | registry &operator=(const registry &) = delete; 32 | 33 | void register_logger(std::shared_ptr new_logger); 34 | void initialize_logger(std::shared_ptr new_logger); 35 | std::shared_ptr get(const std::string &logger_name); 36 | std::shared_ptr default_logger(); 37 | 38 | // Return raw ptr to the default logger. 39 | // To be used directly by the spdlog default api (e.g. spdlog::info) 40 | // This make the default API faster, but cannot be used concurrently with set_default_logger(). 41 | // e.g do not call set_default_logger() from one thread while calling spdlog::info() from another. 42 | logger *get_default_raw(); 43 | 44 | // set default logger. 45 | // default logger is stored in default_logger_ (for faster retrieval) and in the loggers_ map. 46 | void set_default_logger(std::shared_ptr new_default_logger); 47 | 48 | void set_tp(std::shared_ptr tp); 49 | 50 | std::shared_ptr get_tp(); 51 | 52 | // Set global formatter. Each sink in each logger will get a clone of this object 53 | void set_formatter(std::unique_ptr formatter); 54 | 55 | void enable_backtrace(size_t n_messages); 56 | 57 | void disable_backtrace(); 58 | 59 | void set_level(level::level_enum log_level); 60 | 61 | void flush_on(level::level_enum log_level); 62 | 63 | void flush_every(std::chrono::seconds interval); 64 | 65 | void set_error_handler(void (*handler)(const std::string &msg)); 66 | 67 | void apply_all(const std::function)> &fun); 68 | 69 | void flush_all(); 70 | 71 | void drop(const std::string &logger_name); 72 | 73 | void drop_all(); 74 | 75 | // clean all resources and threads started by the registry 76 | void shutdown(); 77 | 78 | std::recursive_mutex &tp_mutex(); 79 | 80 | void set_automatic_registration(bool automatic_regsistration); 81 | 82 | static registry &instance(); 83 | 84 | private: 85 | registry(); 86 | ~registry() = default; 87 | 88 | void throw_if_exists_(const std::string &logger_name); 89 | void register_logger_(std::shared_ptr new_logger); 90 | std::mutex logger_map_mutex_, flusher_mutex_; 91 | std::recursive_mutex tp_mutex_; 92 | std::unordered_map> loggers_; 93 | std::unique_ptr formatter_; 94 | level::level_enum level_ = level::info; 95 | level::level_enum flush_level_ = level::off; 96 | void (*err_handler_)(const std::string &msg); 97 | std::shared_ptr tp_; 98 | std::unique_ptr periodic_flusher_; 99 | std::shared_ptr default_logger_; 100 | bool automatic_registration_ = true; 101 | size_t backtrace_n_messages_ = 0; 102 | }; 103 | 104 | } // namespace details 105 | } // namespace spdlog 106 | 107 | #ifdef SPDLOG_HEADER_ONLY 108 | #include "registry-inl.h" 109 | #endif 110 | -------------------------------------------------------------------------------- /spdlog/sinks/android_sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifdef __ANDROID__ 7 | 8 | #include "spdlog/details/fmt_helper.h" 9 | #include "spdlog/details/null_mutex.h" 10 | #include "spdlog/details/os.h" 11 | #include "spdlog/sinks/base_sink.h" 12 | #include "spdlog/details/synchronous_factory.h" 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #if !defined(SPDLOG_ANDROID_RETRIES) 21 | #define SPDLOG_ANDROID_RETRIES 2 22 | #endif 23 | 24 | namespace spdlog { 25 | namespace sinks { 26 | 27 | /* 28 | * Android sink (logging using __android_log_write) 29 | */ 30 | template 31 | class android_sink final : public base_sink 32 | { 33 | public: 34 | explicit android_sink(std::string tag = "spdlog", bool use_raw_msg = false) 35 | : tag_(std::move(tag)) 36 | , use_raw_msg_(use_raw_msg) 37 | {} 38 | 39 | protected: 40 | void sink_it_(const details::log_msg &msg) override 41 | { 42 | const android_LogPriority priority = convert_to_android_(msg.level); 43 | memory_buf_t formatted; 44 | if (use_raw_msg_) 45 | { 46 | details::fmt_helper::append_string_view(msg.payload, formatted); 47 | } 48 | else 49 | { 50 | base_sink::formatter_->format(msg, formatted); 51 | } 52 | formatted.push_back('\0'); 53 | const char *msg_output = formatted.data(); 54 | 55 | // See system/core/liblog/logger_write.c for explanation of return value 56 | int ret = __android_log_write(priority, tag_.c_str(), msg_output); 57 | int retry_count = 0; 58 | while ((ret == -11 /*EAGAIN*/) && (retry_count < SPDLOG_ANDROID_RETRIES)) 59 | { 60 | details::os::sleep_for_millis(5); 61 | ret = __android_log_write(priority, tag_.c_str(), msg_output); 62 | retry_count++; 63 | } 64 | 65 | if (ret < 0) 66 | { 67 | SPDLOG_THROW(spdlog_ex("__android_log_write() failed", ret)); 68 | } 69 | } 70 | 71 | void flush_() override {} 72 | 73 | private: 74 | static android_LogPriority convert_to_android_(spdlog::level::level_enum level) 75 | { 76 | switch (level) 77 | { 78 | case spdlog::level::trace: 79 | return ANDROID_LOG_VERBOSE; 80 | case spdlog::level::debug: 81 | return ANDROID_LOG_DEBUG; 82 | case spdlog::level::info: 83 | return ANDROID_LOG_INFO; 84 | case spdlog::level::warn: 85 | return ANDROID_LOG_WARN; 86 | case spdlog::level::err: 87 | return ANDROID_LOG_ERROR; 88 | case spdlog::level::critical: 89 | return ANDROID_LOG_FATAL; 90 | default: 91 | return ANDROID_LOG_DEFAULT; 92 | } 93 | } 94 | 95 | std::string tag_; 96 | bool use_raw_msg_; 97 | }; 98 | 99 | using android_sink_mt = android_sink; 100 | using android_sink_st = android_sink; 101 | } // namespace sinks 102 | 103 | // Create and register android syslog logger 104 | 105 | template 106 | inline std::shared_ptr android_logger_mt(const std::string &logger_name, const std::string &tag = "spdlog") 107 | { 108 | return Factory::template create(logger_name, tag); 109 | } 110 | 111 | template 112 | inline std::shared_ptr android_logger_st(const std::string &logger_name, const std::string &tag = "spdlog") 113 | { 114 | return Factory::template create(logger_name, tag); 115 | } 116 | 117 | } // namespace spdlog 118 | 119 | #endif // __ANDROID__ -------------------------------------------------------------------------------- /spdlog/details/file_helper-inl.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifndef SPDLOG_HEADER_ONLY 7 | #include "spdlog/details/file_helper.h" 8 | #endif 9 | 10 | #include "spdlog/details/os.h" 11 | #include "spdlog/common.h" 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | namespace spdlog { 21 | namespace details { 22 | 23 | SPDLOG_INLINE file_helper::~file_helper() 24 | { 25 | close(); 26 | } 27 | 28 | SPDLOG_INLINE void file_helper::open(const filename_t &fname, bool truncate) 29 | { 30 | close(); 31 | auto *mode = truncate ? SPDLOG_FILENAME_T("wb") : SPDLOG_FILENAME_T("ab"); 32 | _filename = fname; 33 | for (int tries = 0; tries < open_tries; ++tries) 34 | { 35 | if (!os::fopen_s(&fd_, fname, mode)) 36 | { 37 | return; 38 | } 39 | 40 | details::os::sleep_for_millis(open_interval); 41 | } 42 | 43 | SPDLOG_THROW(spdlog_ex("Failed opening file " + os::filename_to_str(_filename) + " for writing", errno)); 44 | } 45 | 46 | SPDLOG_INLINE void file_helper::reopen(bool truncate) 47 | { 48 | if (_filename.empty()) 49 | { 50 | SPDLOG_THROW(spdlog_ex("Failed re opening file - was not opened before")); 51 | } 52 | open(_filename, truncate); 53 | } 54 | 55 | SPDLOG_INLINE void file_helper::flush() 56 | { 57 | std::fflush(fd_); 58 | } 59 | 60 | SPDLOG_INLINE void file_helper::close() 61 | { 62 | if (fd_ != nullptr) 63 | { 64 | std::fclose(fd_); 65 | fd_ = nullptr; 66 | } 67 | } 68 | 69 | SPDLOG_INLINE void file_helper::write(const memory_buf_t &buf) 70 | { 71 | size_t msg_size = buf.size(); 72 | auto data = buf.data(); 73 | if (std::fwrite(data, 1, msg_size, fd_) != msg_size) 74 | { 75 | SPDLOG_THROW(spdlog_ex("Failed writing to file " + os::filename_to_str(_filename), errno)); 76 | } 77 | } 78 | 79 | SPDLOG_INLINE size_t file_helper::size() const 80 | { 81 | if (fd_ == nullptr) 82 | { 83 | SPDLOG_THROW(spdlog_ex("Cannot use size() on closed file " + os::filename_to_str(_filename))); 84 | } 85 | return os::filesize(fd_); 86 | } 87 | 88 | SPDLOG_INLINE const filename_t &file_helper::filename() const 89 | { 90 | return _filename; 91 | } 92 | 93 | SPDLOG_INLINE bool file_helper::file_exists(const filename_t &fname) 94 | { 95 | return os::file_exists(fname); 96 | } 97 | 98 | // 99 | // return file path and its extension: 100 | // 101 | // "mylog.txt" => ("mylog", ".txt") 102 | // "mylog" => ("mylog", "") 103 | // "mylog." => ("mylog.", "") 104 | // "/dir1/dir2/mylog.txt" => ("/dir1/dir2/mylog", ".txt") 105 | // 106 | // the starting dot in filenames is ignored (hidden files): 107 | // 108 | // ".mylog" => (".mylog". "") 109 | // "my_folder/.mylog" => ("my_folder/.mylog", "") 110 | // "my_folder/.mylog.txt" => ("my_folder/.mylog", ".txt") 111 | SPDLOG_INLINE std::tuple file_helper::split_by_extension(const filename_t &fname) 112 | { 113 | auto ext_index = fname.rfind('.'); 114 | 115 | // no valid extension found - return whole path and empty string as 116 | // extension 117 | if (ext_index == filename_t::npos || ext_index == 0 || ext_index == fname.size() - 1) 118 | { 119 | return std::make_tuple(fname, filename_t()); 120 | } 121 | 122 | // treat casese like "/etc/rc.d/somelogfile or "/abc/.hiddenfile" 123 | auto folder_index = fname.rfind(details::os::folder_sep); 124 | if (folder_index != filename_t::npos && folder_index >= ext_index - 1) 125 | { 126 | return std::make_tuple(fname, filename_t()); 127 | } 128 | 129 | // finally - return a valid base and extension tuple 130 | return std::make_tuple(fname.substr(0, ext_index), fname.substr(ext_index)); 131 | } 132 | } // namespace details 133 | } // namespace spdlog 134 | -------------------------------------------------------------------------------- /spdlog/details/mpmc_blocking_q.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | // multi producer-multi consumer blocking queue. 7 | // enqueue(..) - will block until room found to put the new message. 8 | // enqueue_nowait(..) - will return immediately with false if no room left in 9 | // the queue. 10 | // dequeue_for(..) - will block until the queue is not empty or timeout have 11 | // passed. 12 | 13 | #include "spdlog/details/circular_q.h" 14 | 15 | #include 16 | #include 17 | 18 | namespace spdlog { 19 | namespace details { 20 | 21 | template 22 | class mpmc_blocking_queue 23 | { 24 | public: 25 | using item_type = T; 26 | explicit mpmc_blocking_queue(size_t max_items) 27 | : q_(max_items) 28 | {} 29 | 30 | #ifndef __MINGW32__ 31 | // try to enqueue and block if no room left 32 | void enqueue(T &&item) 33 | { 34 | { 35 | std::unique_lock lock(queue_mutex_); 36 | pop_cv_.wait(lock, [this] { return !this->q_.full(); }); 37 | q_.push_back(std::move(item)); 38 | } 39 | push_cv_.notify_one(); 40 | } 41 | 42 | // enqueue immediately. overrun oldest message in the queue if no room left. 43 | void enqueue_nowait(T &&item) 44 | { 45 | { 46 | std::unique_lock lock(queue_mutex_); 47 | q_.push_back(std::move(item)); 48 | } 49 | push_cv_.notify_one(); 50 | } 51 | 52 | // try to dequeue item. if no item found. wait upto timeout and try again 53 | // Return true, if succeeded dequeue item, false otherwise 54 | bool dequeue_for(T &popped_item, std::chrono::milliseconds wait_duration) 55 | { 56 | { 57 | std::unique_lock lock(queue_mutex_); 58 | if (!push_cv_.wait_for(lock, wait_duration, [this] { return !this->q_.empty(); })) 59 | { 60 | return false; 61 | } 62 | popped_item = std::move(q_.front()); 63 | q_.pop_front(); 64 | } 65 | pop_cv_.notify_one(); 66 | return true; 67 | } 68 | 69 | #else 70 | // apparently mingw deadlocks if the mutex is released before cv.notify_one(), 71 | // so release the mutex at the very end each function. 72 | 73 | // try to enqueue and block if no room left 74 | void enqueue(T &&item) 75 | { 76 | std::unique_lock lock(queue_mutex_); 77 | pop_cv_.wait(lock, [this] { return !this->q_.full(); }); 78 | q_.push_back(std::move(item)); 79 | push_cv_.notify_one(); 80 | } 81 | 82 | // enqueue immediately. overrun oldest message in the queue if no room left. 83 | void enqueue_nowait(T &&item) 84 | { 85 | std::unique_lock lock(queue_mutex_); 86 | q_.push_back(std::move(item)); 87 | push_cv_.notify_one(); 88 | } 89 | 90 | // try to dequeue item. if no item found. wait upto timeout and try again 91 | // Return true, if succeeded dequeue item, false otherwise 92 | bool dequeue_for(T &popped_item, std::chrono::milliseconds wait_duration) 93 | { 94 | std::unique_lock lock(queue_mutex_); 95 | if (!push_cv_.wait_for(lock, wait_duration, [this] { return !this->q_.empty(); })) 96 | { 97 | return false; 98 | } 99 | popped_item = std::move(q_.front()); 100 | q_.pop_front(); 101 | pop_cv_.notify_one(); 102 | return true; 103 | } 104 | 105 | #endif 106 | 107 | size_t overrun_counter() 108 | { 109 | std::unique_lock lock(queue_mutex_); 110 | return q_.overrun_counter(); 111 | } 112 | 113 | private: 114 | std::mutex queue_mutex_; 115 | std::condition_variable push_cv_; 116 | std::condition_variable pop_cv_; 117 | spdlog::details::circular_q q_; 118 | }; 119 | } // namespace details 120 | } // namespace spdlog 121 | -------------------------------------------------------------------------------- /example/http.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | class HttpDataSource 9 | { 10 | public: 11 | virtual ~HttpDataSource() {} 12 | 13 | virtual void* OpenFile(const std::string& strFile, int64_t offset, int nPreBuffSize = 2*1024*1024) = 0; 14 | virtual int64_t GetFileSize(void *pFileHandle) = 0; 15 | //virtual int64_t GetFileStartPos(const std::string& strFile) = 0; 16 | 17 | virtual int ReadData(void* pFileHandle, int64_t offset, char* pBuffer, int nSize) = 0; 18 | virtual std::string GetFileEtag(void *pFileHandle) = 0; 19 | virtual void CloseFile(void* pFileHandle) = 0; 20 | }; 21 | 22 | class Http 23 | { 24 | public: 25 | enum HttpMethod//HTTP method 26 | { 27 | HM_GET, 28 | HM_POST, 29 | HM_PUT, 30 | HM_HEAD, 31 | HM_CONNECT, 32 | HM_DELETE, 33 | HM_OPTIONS, 34 | HM_TRACE 35 | }; 36 | 37 | static void DecodeUrlParam(const std::string& strUrl, std::string& strPathFile, std::map& mapParam); 38 | static bool DecodeHttpRequestRangeLine(const std::string& strLine, int64_t& nBegin); 39 | static bool DecodeHttpRequestRangeLine(const std::string& strLine, int64_t& nBegin, int64_t& nEnd); 40 | static bool DecodeHttpRequestLine(const std::string& strLine, std::string& strReq, std::string& strPath, std::string& strHttpVer); 41 | static bool DecodeHttpResponseHead(const std::string& strLine, std::string &strField, std::string &strValue); 42 | 43 | static bool DecodeHttpContentRange(const std::string& strLine, std::string &strBytesUnit, int64_t &nBegin, int64_t &nEnd, int64_t &nSize); 44 | 45 | static bool DecodeHttpStatusLine(const std::string& strLine, std::string& strVersion, int &nResponseCode); 46 | }; 47 | 48 | class HttpRequest 49 | { 50 | public: 51 | typedef std::map HttpFieldValueMapT; 52 | 53 | HttpRequest() : m_eHttpMethod(Http::HM_GET) {} 54 | 55 | virtual ~HttpRequest() {} 56 | 57 | bool Decode(const char* pData, int nSize); 58 | std::string GetHttpRequestField(const std::string& strField) const; 59 | 60 | std::string GetReqPathFile() const { return m_strPathFile; } 61 | 62 | const std::string& GetUrlObj() const { return m_strUrl; } 63 | const HttpFieldValueMapT& GetFieldKeyValue() const { return m_mapFieldValue; } 64 | 65 | private: 66 | HttpFieldValueMapT m_mapFieldValue; 67 | 68 | //std::string m_strHttpRequestHead; 69 | std::string m_strHttpRequestData; 70 | std::string m_strPathFile; 71 | std::string m_strUrl; 72 | 73 | Http::HttpMethod m_eHttpMethod; 74 | }; 75 | 76 | class HttpResponseHead 77 | { 78 | public: 79 | HttpResponseHead() {} 80 | virtual ~HttpResponseHead() {} 81 | 82 | bool Decode(const char* pData, int nSize); 83 | int GetStatusCode() const { return m_nStatusCode; } 84 | 85 | bool ExistField(const std::string& strField) const; 86 | std::string GetField(const std::string& strField) const; 87 | 88 | std::list GetCookies() const; 89 | 90 | inline const std::string& GetRedirectUrl() const { return m_strRedirectUrl; } 91 | inline const std::string& GetDispositionFileName() const { return m_strDispositionFileName; } 92 | 93 | inline bool IsChunkTransferCoding() const { return m_bIsChunkTransferCoding; } 94 | 95 | int64_t GetContentSumSize() const; 96 | 97 | inline int64_t GetContentLength() const { return m_nContentLength; } 98 | inline int64_t GetContentBeginPos() const { return m_nContentBeginPos; } 99 | inline int64_t GetContentEndPos() const { return m_nContentEndPos; } 100 | 101 | private: 102 | bool DecodeResponseParameter(const std::string& strField, const std::string& strValue); 103 | void InitMember(); 104 | 105 | std::string m_strResponseHead; 106 | int m_nStatusCode; 107 | 108 | std::string m_strRedirectUrl; 109 | std::string m_strDispositionFileName; 110 | 111 | bool m_bIsChunkTransferCoding; 112 | 113 | int64_t m_nContentLength; 114 | 115 | int64_t m_nContentBeginPos; 116 | int64_t m_nContentEndPos; 117 | int64_t m_nContentSumLength; 118 | 119 | typedef std::multimap HttpFieldValueMapT; 120 | HttpFieldValueMapT m_mapFieldValue; 121 | }; -------------------------------------------------------------------------------- /spdlog/sinks/syslog_sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include "spdlog/sinks/base_sink.h" 7 | #include "spdlog/details/null_mutex.h" 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | namespace spdlog { 14 | namespace sinks { 15 | /** 16 | * Sink that write to syslog using the `syscall()` library call. 17 | */ 18 | template 19 | class syslog_sink : public base_sink 20 | { 21 | 22 | public: 23 | syslog_sink(std::string ident, int syslog_option, int syslog_facility, bool enable_formatting) 24 | : enable_formatting_{enable_formatting} 25 | , syslog_levels_{{/* spdlog::level::trace */ LOG_DEBUG, 26 | /* spdlog::level::debug */ LOG_DEBUG, 27 | /* spdlog::level::info */ LOG_INFO, 28 | /* spdlog::level::warn */ LOG_WARNING, 29 | /* spdlog::level::err */ LOG_ERR, 30 | /* spdlog::level::critical */ LOG_CRIT, 31 | /* spdlog::level::off */ LOG_INFO}} 32 | , ident_{std::move(ident)} 33 | { 34 | // set ident to be program name if empty 35 | ::openlog(ident_.empty() ? nullptr : ident_.c_str(), syslog_option, syslog_facility); 36 | } 37 | 38 | ~syslog_sink() override 39 | { 40 | ::closelog(); 41 | } 42 | 43 | syslog_sink(const syslog_sink &) = delete; 44 | syslog_sink &operator=(const syslog_sink &) = delete; 45 | 46 | protected: 47 | void sink_it_(const details::log_msg &msg) override 48 | { 49 | string_view_t payload; 50 | memory_buf_t formatted; 51 | if (enable_formatting_) 52 | { 53 | base_sink::formatter_->format(msg, formatted); 54 | payload = string_view_t(formatted.data(), formatted.size()); 55 | } 56 | else 57 | { 58 | payload = msg.payload; 59 | } 60 | 61 | size_t length = payload.size(); 62 | // limit to max int 63 | if (length > static_cast(std::numeric_limits::max())) 64 | { 65 | length = static_cast(std::numeric_limits::max()); 66 | } 67 | 68 | ::syslog(syslog_prio_from_level(msg), "%.*s", static_cast(length), payload.data()); 69 | } 70 | 71 | void flush_() override {} 72 | bool enable_formatting_ = false; 73 | 74 | private: 75 | using levels_array = std::array; 76 | levels_array syslog_levels_; 77 | // must store the ident because the man says openlog might use the pointer as 78 | // is and not a string copy 79 | const std::string ident_; 80 | 81 | // 82 | // Simply maps spdlog's log level to syslog priority level. 83 | // 84 | int syslog_prio_from_level(const details::log_msg &msg) const 85 | { 86 | return syslog_levels_.at(static_cast(msg.level)); 87 | } 88 | }; 89 | 90 | using syslog_sink_mt = syslog_sink; 91 | using syslog_sink_st = syslog_sink; 92 | } // namespace sinks 93 | 94 | // Create and register a syslog logger 95 | template 96 | inline std::shared_ptr syslog_logger_mt(const std::string &logger_name, const std::string &syslog_ident = "", int syslog_option = 0, 97 | int syslog_facility = LOG_USER, bool enable_formatting = false) 98 | { 99 | return Factory::template create(logger_name, syslog_ident, syslog_option, syslog_facility, enable_formatting); 100 | } 101 | 102 | template 103 | inline std::shared_ptr syslog_logger_st(const std::string &logger_name, const std::string &syslog_ident = "", int syslog_option = 0, 104 | int syslog_facility = LOG_USER, bool enable_formatting = false) 105 | { 106 | return Factory::template create(logger_name, syslog_ident, syslog_option, syslog_facility, enable_formatting); 107 | } 108 | } // namespace spdlog 109 | -------------------------------------------------------------------------------- /utp_common.h: -------------------------------------------------------------------------------- 1 | #if !defined(AFX_COMMON_H__FB063327_573C_4D70_A0B4_ECC067B6F4FD__INCLUDED_) 2 | #define AFX_COMMON_H__FB063327_573C_4D70_A0B4_ECC067B6F4FD__INCLUDED_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | namespace rtttech_utp 12 | { 13 | inline int64_t GetMicroSecondsSinceEpoch() 14 | { 15 | uint64_t us = std::chrono::duration_cast(std::chrono::high_resolution_clock:: 16 | now().time_since_epoch()).count(); 17 | return us; 18 | } 19 | 20 | template 21 | class CircleSeq 22 | { 23 | public: 24 | CircleSeq(T seq) : seq_num(seq) {} 25 | bool operator < (const CircleSeq& r) const { return ((T2)((seq_num)-(r.seq_num)) < 0); } 26 | bool operator <= (const CircleSeq& r) const { return ((T2)((seq_num)-(r.seq_num)) <= 0); } 27 | 28 | bool operator > (const CircleSeq& r) const { return r < *this; } 29 | bool operator >= (const CircleSeq& r) const { return r <= *this; } 30 | 31 | bool operator == (const CircleSeq& r) const { return seq_num == r.seq_num; } 32 | bool operator == (const uint32_t r) const { return seq_num == r; }; 33 | 34 | T operator - (const CircleSeq& r) const { return (T)((seq_num)-(r.seq_num)); } 35 | CircleSeq operator + (const CircleSeq& r) const { return CircleSeq(seq_num + r.seq_num); } 36 | 37 | void operator += (const T r) { seq_num += r; } 38 | 39 | explicit operator T () const { return seq_num; } 40 | private: 41 | T seq_num; 42 | }; 43 | 44 | class UTPClock 45 | { 46 | public: 47 | UTPClock() {} 48 | virtual ~UTPClock() {} 49 | 50 | virtual int64_t GetMicroSecond() const 51 | { 52 | return GetMicroSecondsSinceEpoch(); 53 | } 54 | }; 55 | 56 | class LostCounter 57 | { 58 | public: 59 | LostCounter(int duration = 3 * 1000 * 1000, int history = 20) 60 | : m_nDuration(duration), m_nKeepHistory(history) {} 61 | 62 | void OnPacketAcked(uint64_t tm) 63 | { 64 | m_deqLostInfo.push_back(Item(tm, false)); 65 | ++m_nTotalPktNum; 66 | UpdateItem(tm); 67 | } 68 | 69 | void OnPacketLost(uint64_t tm) 70 | { 71 | m_deqLostInfo.push_back(Item(tm, true)); 72 | ++m_nLostPktNum; 73 | ++m_nTotalPktNum; 74 | UpdateItem(tm); 75 | } 76 | 77 | void UpdateItem(uint64_t tm) 78 | { 79 | while (m_deqLostInfo.size() > m_nKeepHistory) 80 | { 81 | Item &itm = m_deqLostInfo[0]; 82 | if (tm - m_deqLostInfo[0].time > m_nDuration || tm < m_deqLostInfo[0].time) { 83 | 84 | if (itm.lost) { 85 | --m_nLostPktNum; 86 | } 87 | m_deqLostInfo.pop_front(); 88 | --m_nTotalPktNum; 89 | } 90 | else { 91 | break; 92 | } 93 | } 94 | } 95 | 96 | int GetLostPercent() const 97 | { 98 | if (m_nTotalPktNum == 0) 99 | return 0; 100 | else 101 | return 100 * m_nLostPktNum / m_nTotalPktNum; 102 | } 103 | 104 | private: 105 | 106 | struct Item 107 | { 108 | Item(uint64_t tm, bool b) : time(tm), lost(b) {} 109 | uint64_t time; 110 | bool lost; 111 | }; 112 | 113 | std::deque m_deqLostInfo; 114 | int m_nTotalPktNum = 0; 115 | int m_nLostPktNum = 0; 116 | int m_nDuration; 117 | int m_nKeepHistory; 118 | }; 119 | 120 | void BitmapSet(int pos, bool b, char* buff, int len); 121 | bool BitmapGet(int pos, const char* buff, int len); 122 | std::string Bitmap01String(const char* buff, int len); 123 | 124 | int GenerateAckBitfield(CircleSeq next_expect, const std::vector>& seqvec, char* bitbuff, int buffsize); 125 | 126 | int GetBitmapBits(CircleSeq next_expect, CircleSeq seq_max, int seq_queue_size); 127 | 128 | int XorData(const char* data1, int len1, const char* data2, int len2, char* out, int outlen); 129 | 130 | std::string GenerateUUID(); 131 | 132 | void AssertFailLog(const char *szExpr, const char *szFile, unsigned int nLine); 133 | 134 | #define RTASSERT(expr) if (!(expr)) { AssertFailLog( #expr, __FILE__, __LINE__); assert(expr);} 135 | } 136 | 137 | #endif 138 | -------------------------------------------------------------------------------- /spdlog/sinks/ansicolor_sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include "spdlog/details/console_globals.h" 7 | #include "spdlog/details/null_mutex.h" 8 | #include "spdlog/sinks/sink.h" 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | namespace spdlog { 15 | namespace sinks { 16 | 17 | /** 18 | * This sink prefixes the output with an ANSI escape sequence color code 19 | * depending on the severity 20 | * of the message. 21 | * If no color terminal detected, omit the escape codes. 22 | */ 23 | 24 | template 25 | class ansicolor_sink : public sink 26 | { 27 | public: 28 | using mutex_t = typename ConsoleMutex::mutex_t; 29 | ansicolor_sink(FILE *target_file, color_mode mode); 30 | ~ansicolor_sink() override = default; 31 | 32 | ansicolor_sink(const ansicolor_sink &other) = delete; 33 | ansicolor_sink &operator=(const ansicolor_sink &other) = delete; 34 | void set_color(level::level_enum color_level, string_view_t color); 35 | void set_color_mode(color_mode mode); 36 | bool should_color(); 37 | 38 | void log(const details::log_msg &msg) override; 39 | void flush() override; 40 | void set_pattern(const std::string &pattern) final; 41 | void set_formatter(std::unique_ptr sink_formatter) override; 42 | 43 | // Formatting codes 44 | const string_view_t reset = "\033[m"; 45 | const string_view_t bold = "\033[1m"; 46 | const string_view_t dark = "\033[2m"; 47 | const string_view_t underline = "\033[4m"; 48 | const string_view_t blink = "\033[5m"; 49 | const string_view_t reverse = "\033[7m"; 50 | const string_view_t concealed = "\033[8m"; 51 | const string_view_t clear_line = "\033[K"; 52 | 53 | // Foreground colors 54 | const string_view_t black = "\033[30m"; 55 | const string_view_t red = "\033[31m"; 56 | const string_view_t green = "\033[32m"; 57 | const string_view_t yellow = "\033[33m"; 58 | const string_view_t blue = "\033[34m"; 59 | const string_view_t magenta = "\033[35m"; 60 | const string_view_t cyan = "\033[36m"; 61 | const string_view_t white = "\033[37m"; 62 | 63 | /// Background colors 64 | const string_view_t on_black = "\033[40m"; 65 | const string_view_t on_red = "\033[41m"; 66 | const string_view_t on_green = "\033[42m"; 67 | const string_view_t on_yellow = "\033[43m"; 68 | const string_view_t on_blue = "\033[44m"; 69 | const string_view_t on_magenta = "\033[45m"; 70 | const string_view_t on_cyan = "\033[46m"; 71 | const string_view_t on_white = "\033[47m"; 72 | 73 | /// Bold colors 74 | const string_view_t yellow_bold = "\033[33m\033[1m"; 75 | const string_view_t red_bold = "\033[31m\033[1m"; 76 | const string_view_t bold_on_red = "\033[1m\033[41m"; 77 | 78 | private: 79 | FILE *target_file_; 80 | mutex_t &mutex_; 81 | bool should_do_colors_; 82 | std::unique_ptr formatter_; 83 | std::unordered_map colors_; 84 | void print_ccode_(const string_view_t &color_code); 85 | void print_range_(const memory_buf_t &formatted, size_t start, size_t end); 86 | }; 87 | 88 | template 89 | class ansicolor_stdout_sink : public ansicolor_sink 90 | { 91 | public: 92 | explicit ansicolor_stdout_sink(color_mode mode = color_mode::automatic); 93 | }; 94 | 95 | template 96 | class ansicolor_stderr_sink : public ansicolor_sink 97 | { 98 | public: 99 | explicit ansicolor_stderr_sink(color_mode mode = color_mode::automatic); 100 | }; 101 | 102 | using ansicolor_stdout_sink_mt = ansicolor_stdout_sink; 103 | using ansicolor_stdout_sink_st = ansicolor_stdout_sink; 104 | 105 | using ansicolor_stderr_sink_mt = ansicolor_stderr_sink; 106 | using ansicolor_stderr_sink_st = ansicolor_stderr_sink; 107 | 108 | } // namespace sinks 109 | } // namespace spdlog 110 | 111 | #ifdef SPDLOG_HEADER_ONLY 112 | #include "ansicolor_sink-inl.h" 113 | #endif 114 | -------------------------------------------------------------------------------- /spdlog/sinks/rotating_file_sink-inl.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifndef SPDLOG_HEADER_ONLY 7 | #include "spdlog/sinks/rotating_file_sink.h" 8 | #endif 9 | 10 | #include "spdlog/common.h" 11 | 12 | #include "spdlog/details/file_helper.h" 13 | #include "spdlog/details/null_mutex.h" 14 | #include "spdlog/fmt/fmt.h" 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | namespace spdlog { 24 | namespace sinks { 25 | 26 | template 27 | SPDLOG_INLINE rotating_file_sink::rotating_file_sink( 28 | filename_t base_filename, std::size_t max_size, std::size_t max_files, bool rotate_on_open) 29 | : base_filename_(std::move(base_filename)) 30 | , max_size_(max_size) 31 | , max_files_(max_files) 32 | { 33 | file_helper_.open(calc_filename(base_filename_, 0)); 34 | current_size_ = file_helper_.size(); // expensive. called only once 35 | if (rotate_on_open && current_size_ > 0) 36 | { 37 | rotate_(); 38 | } 39 | } 40 | 41 | // calc filename according to index and file extension if exists. 42 | // e.g. calc_filename("logs/mylog.txt, 3) => "logs/mylog.3.txt". 43 | template 44 | SPDLOG_INLINE filename_t rotating_file_sink::calc_filename(const filename_t &filename, std::size_t index) 45 | { 46 | if (index == 0u) 47 | { 48 | return filename; 49 | } 50 | 51 | filename_t basename, ext; 52 | std::tie(basename, ext) = details::file_helper::split_by_extension(filename); 53 | return fmt::format(SPDLOG_FILENAME_T("{}.{}{}"), basename, index, ext); 54 | } 55 | 56 | template 57 | SPDLOG_INLINE const filename_t &rotating_file_sink::filename() const 58 | { 59 | return file_helper_.filename(); 60 | } 61 | 62 | template 63 | SPDLOG_INLINE void rotating_file_sink::sink_it_(const details::log_msg &msg) 64 | { 65 | memory_buf_t formatted; 66 | base_sink::formatter_->format(msg, formatted); 67 | current_size_ += formatted.size(); 68 | if (current_size_ > max_size_) 69 | { 70 | rotate_(); 71 | current_size_ = formatted.size(); 72 | } 73 | file_helper_.write(formatted); 74 | } 75 | 76 | template 77 | SPDLOG_INLINE void rotating_file_sink::flush_() 78 | { 79 | file_helper_.flush(); 80 | } 81 | 82 | // Rotate files: 83 | // log.txt -> log.1.txt 84 | // log.1.txt -> log.2.txt 85 | // log.2.txt -> log.3.txt 86 | // log.3.txt -> delete 87 | template 88 | SPDLOG_INLINE void rotating_file_sink::rotate_() 89 | { 90 | using details::os::filename_to_str; 91 | file_helper_.close(); 92 | for (auto i = max_files_; i > 0; --i) 93 | { 94 | filename_t src = calc_filename(base_filename_, i - 1); 95 | if (!details::file_helper::file_exists(src)) 96 | { 97 | continue; 98 | } 99 | filename_t target = calc_filename(base_filename_, i); 100 | 101 | if (!rename_file(src, target)) 102 | { 103 | // if failed try again after a small delay. 104 | // this is a workaround to a windows issue, where very high rotation 105 | // rates can cause the rename to fail with permission denied (because of antivirus?). 106 | details::os::sleep_for_millis(100); 107 | if (!rename_file(src, target)) 108 | { 109 | file_helper_.reopen(true); // truncate the log file anyway to prevent it to grow beyond its limit! 110 | current_size_ = 0; 111 | SPDLOG_THROW( 112 | spdlog_ex("rotating_file_sink: failed renaming " + filename_to_str(src) + " to " + filename_to_str(target), errno)); 113 | } 114 | } 115 | } 116 | file_helper_.reopen(true); 117 | } 118 | 119 | // delete the target if exists, and rename the src file to target 120 | // return true on success, false otherwise. 121 | template 122 | SPDLOG_INLINE bool rotating_file_sink::rename_file(const filename_t &src_filename, const filename_t &target_filename) 123 | { 124 | // try to delete the target file in case it already exists. 125 | (void)details::os::remove(target_filename); 126 | return details::os::rename(src_filename, target_filename) == 0; 127 | } 128 | 129 | } // namespace sinks 130 | } // namespace spdlog 131 | -------------------------------------------------------------------------------- /spdlog/sinks/ansicolor_sink-inl.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifndef SPDLOG_HEADER_ONLY 7 | #include "spdlog/sinks/ansicolor_sink.h" 8 | #endif 9 | 10 | #include "spdlog/details/pattern_formatter.h" 11 | #include "spdlog/details/os.h" 12 | 13 | namespace spdlog { 14 | namespace sinks { 15 | 16 | template 17 | SPDLOG_INLINE ansicolor_sink::ansicolor_sink(FILE *target_file, color_mode mode) 18 | : target_file_(target_file) 19 | , mutex_(ConsoleMutex::mutex()) 20 | , formatter_(details::make_unique()) 21 | 22 | { 23 | set_color_mode(mode); 24 | colors_[level::trace] = white; 25 | colors_[level::debug] = cyan; 26 | colors_[level::info] = green; 27 | colors_[level::warn] = yellow_bold; 28 | colors_[level::err] = red_bold; 29 | colors_[level::critical] = bold_on_red; 30 | colors_[level::off] = reset; 31 | } 32 | 33 | template 34 | SPDLOG_INLINE void ansicolor_sink::set_color(level::level_enum color_level, string_view_t color) 35 | { 36 | std::lock_guard lock(mutex_); 37 | colors_[color_level] = color; 38 | } 39 | 40 | template 41 | SPDLOG_INLINE void ansicolor_sink::log(const details::log_msg &msg) 42 | { 43 | // Wrap the originally formatted message in color codes. 44 | // If color is not supported in the terminal, log as is instead. 45 | std::lock_guard lock(mutex_); 46 | 47 | memory_buf_t formatted; 48 | formatter_->format(msg, formatted); 49 | if (should_do_colors_ && msg.color_range_end > msg.color_range_start) 50 | { 51 | // before color range 52 | print_range_(formatted, 0, msg.color_range_start); 53 | // in color range 54 | print_ccode_(colors_[msg.level]); 55 | print_range_(formatted, msg.color_range_start, msg.color_range_end); 56 | print_ccode_(reset); 57 | // after color range 58 | print_range_(formatted, msg.color_range_end, formatted.size()); 59 | } 60 | else // no color 61 | { 62 | print_range_(formatted, 0, formatted.size()); 63 | } 64 | fflush(target_file_); 65 | } 66 | 67 | template 68 | SPDLOG_INLINE void ansicolor_sink::flush() 69 | { 70 | std::lock_guard lock(mutex_); 71 | fflush(target_file_); 72 | } 73 | 74 | template 75 | SPDLOG_INLINE void ansicolor_sink::set_pattern(const std::string &pattern) 76 | { 77 | std::lock_guard lock(mutex_); 78 | formatter_ = std::unique_ptr(new pattern_formatter(pattern)); 79 | } 80 | 81 | template 82 | SPDLOG_INLINE void ansicolor_sink::set_formatter(std::unique_ptr sink_formatter) 83 | { 84 | std::lock_guard lock(mutex_); 85 | formatter_ = std::move(sink_formatter); 86 | } 87 | 88 | template 89 | SPDLOG_INLINE bool ansicolor_sink::should_color() 90 | { 91 | return should_do_colors_; 92 | } 93 | 94 | template 95 | SPDLOG_INLINE void ansicolor_sink::set_color_mode(color_mode mode) 96 | { 97 | switch (mode) 98 | { 99 | case color_mode::always: 100 | should_do_colors_ = true; 101 | return; 102 | case color_mode::automatic: 103 | should_do_colors_ = details::os::in_terminal(target_file_) && details::os::is_color_terminal(); 104 | return; 105 | case color_mode::never: 106 | should_do_colors_ = false; 107 | return; 108 | } 109 | } 110 | 111 | template 112 | SPDLOG_INLINE void ansicolor_sink::print_ccode_(const string_view_t &color_code) 113 | { 114 | fwrite(color_code.data(), sizeof(string_view_t::char_type), color_code.size(), target_file_); 115 | } 116 | 117 | template 118 | SPDLOG_INLINE void ansicolor_sink::print_range_(const memory_buf_t &formatted, size_t start, size_t end) 119 | { 120 | fwrite(formatted.data() + start, sizeof(char), end - start, target_file_); 121 | } 122 | 123 | // ansicolor_stdout_sink 124 | template 125 | SPDLOG_INLINE ansicolor_stdout_sink::ansicolor_stdout_sink(color_mode mode) 126 | : ansicolor_sink(stdout, mode) 127 | {} 128 | 129 | // ansicolor_stderr_sink 130 | template 131 | SPDLOG_INLINE ansicolor_stderr_sink::ansicolor_stderr_sink(color_mode mode) 132 | : ansicolor_sink(stderr, mode) 133 | {} 134 | 135 | } // namespace sinks 136 | } // namespace spdlog 137 | -------------------------------------------------------------------------------- /spdlog/fmt/bundled/ostream.h: -------------------------------------------------------------------------------- 1 | // Formatting library for C++ - std::ostream support 2 | // 3 | // Copyright (c) 2012 - present, Victor Zverovich 4 | // All rights reserved. 5 | // 6 | // For the license information refer to format.h. 7 | 8 | #ifndef FMT_OSTREAM_H_ 9 | #define FMT_OSTREAM_H_ 10 | 11 | #include 12 | #include "format.h" 13 | 14 | FMT_BEGIN_NAMESPACE 15 | namespace internal { 16 | 17 | template class formatbuf : public std::basic_streambuf { 18 | private: 19 | using int_type = typename std::basic_streambuf::int_type; 20 | using traits_type = typename std::basic_streambuf::traits_type; 21 | 22 | buffer& buffer_; 23 | 24 | public: 25 | formatbuf(buffer& buf) : buffer_(buf) {} 26 | 27 | protected: 28 | // The put-area is actually always empty. This makes the implementation 29 | // simpler and has the advantage that the streambuf and the buffer are always 30 | // in sync and sputc never writes into uninitialized memory. The obvious 31 | // disadvantage is that each call to sputc always results in a (virtual) call 32 | // to overflow. There is no disadvantage here for sputn since this always 33 | // results in a call to xsputn. 34 | 35 | int_type overflow(int_type ch = traits_type::eof()) FMT_OVERRIDE { 36 | if (!traits_type::eq_int_type(ch, traits_type::eof())) 37 | buffer_.push_back(static_cast(ch)); 38 | return ch; 39 | } 40 | 41 | std::streamsize xsputn(const Char* s, std::streamsize count) FMT_OVERRIDE { 42 | buffer_.append(s, s + count); 43 | return count; 44 | } 45 | }; 46 | 47 | template struct test_stream : std::basic_ostream { 48 | private: 49 | struct null; 50 | // Hide all operator<< from std::basic_ostream. 51 | void operator<<(null); 52 | }; 53 | 54 | // Checks if T has a user-defined operator<< (e.g. not a member of 55 | // std::ostream). 56 | template class is_streamable { 57 | private: 58 | template 59 | static decltype((void)(std::declval&>() 60 | << std::declval()), 61 | std::true_type()) 62 | test(int); 63 | 64 | template static std::false_type test(...); 65 | 66 | using result = decltype(test(0)); 67 | 68 | public: 69 | static const bool value = result::value; 70 | }; 71 | 72 | // Write the content of buf to os. 73 | template 74 | void write(std::basic_ostream& os, buffer& buf) { 75 | const Char* buf_data = buf.data(); 76 | using unsigned_streamsize = std::make_unsigned::type; 77 | unsigned_streamsize size = buf.size(); 78 | unsigned_streamsize max_size = 79 | to_unsigned((std::numeric_limits::max)()); 80 | do { 81 | unsigned_streamsize n = size <= max_size ? size : max_size; 82 | os.write(buf_data, static_cast(n)); 83 | buf_data += n; 84 | size -= n; 85 | } while (size != 0); 86 | } 87 | 88 | template 89 | void format_value(buffer& buf, const T& value) { 90 | formatbuf format_buf(buf); 91 | std::basic_ostream output(&format_buf); 92 | output.exceptions(std::ios_base::failbit | std::ios_base::badbit); 93 | output << value; 94 | buf.resize(buf.size()); 95 | } 96 | 97 | // Formats an object of type T that has an overloaded ostream operator<<. 98 | template 99 | struct fallback_formatter::value>> 100 | : formatter, Char> { 101 | template 102 | auto format(const T& value, Context& ctx) -> decltype(ctx.out()) { 103 | basic_memory_buffer buffer; 104 | format_value(buffer, value); 105 | basic_string_view str(buffer.data(), buffer.size()); 106 | return formatter, Char>::format(str, ctx); 107 | } 108 | }; 109 | } // namespace internal 110 | 111 | template 112 | void vprint(std::basic_ostream& os, basic_string_view format_str, 113 | basic_format_args> args) { 114 | basic_memory_buffer buffer; 115 | internal::vformat_to(buffer, format_str, args); 116 | internal::write(os, buffer); 117 | } 118 | 119 | /** 120 | \rst 121 | Prints formatted data to the stream *os*. 122 | 123 | **Example**:: 124 | 125 | fmt::print(cerr, "Don't {}!", "panic"); 126 | \endrst 127 | */ 128 | template ::value, char_t>> 130 | void print(std::basic_ostream& os, const S& format_str, Args&&... args) { 131 | vprint(os, to_string_view(format_str), 132 | {internal::make_args_checked(format_str, args...)}); 133 | } 134 | FMT_END_NAMESPACE 135 | 136 | #endif // FMT_OSTREAM_H_ 137 | -------------------------------------------------------------------------------- /spdlog/fmt/bin_to_hex.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2015 Gabi Melman. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | 8 | // 9 | // Support for logging binary data as hex 10 | // format flags: 11 | // {:X} - print in uppercase. 12 | // {:s} - don't separate each byte with space. 13 | // {:p} - don't print the position on each line start. 14 | // {:n} - don't split the output to lines. 15 | 16 | // 17 | // Examples: 18 | // 19 | // std::vector v(200, 0x0b); 20 | // logger->info("Some buffer {}", spdlog::to_hex(v)); 21 | // char buf[128]; 22 | // logger->info("Some buffer {:X}", spdlog::to_hex(std::begin(buf), std::end(buf))); 23 | 24 | namespace spdlog { 25 | namespace details { 26 | 27 | template 28 | class bytes_range 29 | { 30 | public: 31 | bytes_range(It range_begin, It range_end) 32 | : begin_(range_begin) 33 | , end_(range_end) 34 | {} 35 | 36 | It begin() const 37 | { 38 | return begin_; 39 | } 40 | It end() const 41 | { 42 | return end_; 43 | } 44 | 45 | private: 46 | It begin_, end_; 47 | }; 48 | } // namespace details 49 | 50 | // create a bytes_range that wraps the given container 51 | template 52 | inline details::bytes_range to_hex(const Container &container) 53 | { 54 | static_assert(sizeof(typename Container::value_type) == 1, "sizeof(Container::value_type) != 1"); 55 | using Iter = typename Container::const_iterator; 56 | return details::bytes_range(std::begin(container), std::end(container)); 57 | } 58 | 59 | // create bytes_range from ranges 60 | template 61 | inline details::bytes_range to_hex(const It range_begin, const It range_end) 62 | { 63 | return details::bytes_range(range_begin, range_end); 64 | } 65 | 66 | } // namespace spdlog 67 | 68 | namespace fmt { 69 | 70 | template 71 | struct formatter> 72 | { 73 | const std::size_t line_size = 100; 74 | const char delimiter = ' '; 75 | 76 | bool put_newlines = true; 77 | bool put_delimiters = true; 78 | bool use_uppercase = false; 79 | bool put_positions = true; // position on start of each line 80 | 81 | // parse the format string flags 82 | template 83 | auto parse(ParseContext &ctx) -> decltype(ctx.begin()) 84 | { 85 | auto it = ctx.begin(); 86 | while (*it && *it != '}') 87 | { 88 | switch (*it) 89 | { 90 | case 'X': 91 | use_uppercase = true; 92 | break; 93 | case 's': 94 | put_delimiters = false; 95 | break; 96 | case 'p': 97 | put_positions = false; 98 | break; 99 | case 'n': 100 | put_newlines = false; 101 | break; 102 | } 103 | 104 | ++it; 105 | } 106 | return it; 107 | } 108 | 109 | // format the given bytes range as hex 110 | template 111 | auto format(const spdlog::details::bytes_range &the_range, FormatContext &ctx) -> decltype(ctx.out()) 112 | { 113 | SPDLOG_CONSTEXPR const char *hex_upper = "0123456789ABCDEF"; 114 | SPDLOG_CONSTEXPR const char *hex_lower = "0123456789abcdef"; 115 | const char *hex_chars = use_uppercase ? hex_upper : hex_lower; 116 | 117 | std::size_t pos = 0; 118 | std::size_t column = line_size; 119 | #if FMT_VERSION < 60000 120 | auto inserter = ctx.begin(); 121 | #else 122 | auto inserter = ctx.out(); 123 | #endif 124 | 125 | for (auto &item : the_range) 126 | { 127 | auto ch = static_cast(item); 128 | pos++; 129 | 130 | if (put_newlines && column >= line_size) 131 | { 132 | column = put_newline(inserter, pos); 133 | 134 | // put first byte without delimiter in front of it 135 | *inserter++ = hex_chars[(ch >> 4) & 0x0f]; 136 | *inserter++ = hex_chars[ch & 0x0f]; 137 | column += 2; 138 | continue; 139 | } 140 | 141 | if (put_delimiters) 142 | { 143 | *inserter++ = delimiter; 144 | ++column; 145 | } 146 | 147 | *inserter++ = hex_chars[(ch >> 4) & 0x0f]; 148 | *inserter++ = hex_chars[ch & 0x0f]; 149 | column += 2; 150 | } 151 | return inserter; 152 | } 153 | 154 | // put newline(and position header) 155 | // return the next column 156 | template 157 | std::size_t put_newline(It inserter, std::size_t pos) 158 | { 159 | #ifdef _WIN32 160 | *inserter++ = '\r'; 161 | #endif 162 | *inserter++ = '\n'; 163 | 164 | if (put_positions) 165 | { 166 | fmt::format_to(inserter, "{:<04X}: ", pos - 1); 167 | return 7; 168 | } 169 | else 170 | { 171 | return 1; 172 | } 173 | } 174 | }; 175 | } // namespace fmt 176 | -------------------------------------------------------------------------------- /example/os_common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef WIN32 4 | #ifndef _CRT_SECURE_NO_DEPRECATE 5 | #define _CRT_SECURE_NO_DEPRECATE 6 | #endif 7 | #ifndef WIN32_LEAN_AND_MEAN 8 | #define WIN32_LEAN_AND_MEAN 9 | #endif 10 | #include 11 | #include 12 | #include 13 | 14 | #else 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | typedef int SOCKET; 27 | #define SOCKET_ERROR -1 28 | 29 | #endif 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #ifdef _MSC_VER 38 | #define IOCTL ioctlsocket 39 | #else 40 | #define IOCTL ioctl 41 | #endif 42 | 43 | struct udp_pkt_send_item 44 | { 45 | udp_pkt_send_item(const char * data, int size, struct sockaddr * sa, int sock_len) 46 | { 47 | buffer = new char[size]; 48 | len = size; 49 | memcpy(buffer, data, len); 50 | memcpy(&addr, sa, sock_len); 51 | addr_len = sock_len; 52 | } 53 | ~udp_pkt_send_item() 54 | { 55 | delete buffer; 56 | } 57 | char* buffer; 58 | int len; 59 | struct sockaddr_storage addr; 60 | int addr_len; 61 | }; 62 | 63 | struct sent_packet_info 64 | { 65 | sent_packet_info() : send_time(0), resp_time(0), pkt_size(0) {} 66 | uint64_t send_time; 67 | uint64_t resp_time; 68 | uint32_t pkt_size; 69 | }; 70 | 71 | struct socket_send_item 72 | { 73 | socket_send_item(const char* buffer, int len) : send_buffer(buffer), send_buff_len(len), send_buff_pos(0) {} 74 | ~socket_send_item() { delete send_buffer; } 75 | 76 | const char* send_buffer; 77 | int send_buff_pos; 78 | int send_buff_len; 79 | }; 80 | 81 | struct socket_io_info 82 | { 83 | enum state {IDLE, CONNECTING, CONNECTED, WAITING_CLOSE, CLOSED}; 84 | socket_io_info() : recv_buffer(NULL), recv_buff_pos(0), recv_buff_len(0), connected_time(0), create_time(get_micro_second()), state(IDLE) {} 85 | ~socket_io_info() { if (recv_buffer) delete recv_buffer; } 86 | 87 | char* recv_buffer; 88 | int recv_buff_pos; 89 | int recv_buff_len; 90 | 91 | uint64_t connected_time; 92 | uint64_t create_time; 93 | state state; 94 | 95 | std::deque> send_deq; 96 | }; 97 | 98 | inline void init_socket() 99 | { 100 | #ifdef _MSC_VER 101 | WSAData wsaData; 102 | int init_ret = ::WSAStartup(MAKEWORD(2, 2), &wsaData); 103 | 104 | #endif 105 | } 106 | 107 | inline SOCKET create_udp_socket(int buffer_size = 1024*1024) 108 | { 109 | #ifdef _MSC_VER 110 | 111 | SOCKET s = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 112 | 113 | u_long arg = 1; 114 | int ret = ::ioctlsocket(s, FIONBIO, &arg); 115 | 116 | #else 117 | SOCKET s = ::socket(AF_INET, SOCK_DGRAM, 0); 118 | int oldflags = ::fcntl(s, F_GETFL, 0); 119 | oldflags |= O_NONBLOCK; 120 | ::fcntl(s, F_SETFL, oldflags); 121 | #endif // _MSC_VER 122 | 123 | 124 | int bf = buffer_size; 125 | int ssrr = setsockopt(s, SOL_SOCKET, SO_RCVBUF, (const char*)&bf, (int)sizeof(bf)); 126 | int sssr = setsockopt(s, SOL_SOCKET, SO_SNDBUF, (const char*)&bf, (int)sizeof(bf)); 127 | if (ssrr != 0 && sssr != 0) { 128 | std::cout << "setsockopt failed" << std::endl; 129 | } 130 | else { 131 | //std::cout << "setsockopt success" << std::endl; 132 | } 133 | 134 | return s; 135 | } 136 | 137 | inline SOCKET create_tcp_socket() 138 | { 139 | #ifdef _MSC_VER 140 | 141 | SOCKET s = ::socket(AF_INET, SOCK_STREAM, 0); 142 | 143 | u_long arg = 1; 144 | int ret = ::ioctlsocket(s, FIONBIO, &arg); 145 | 146 | #else 147 | SOCKET s = ::socket(AF_INET, SOCK_STREAM, 0); 148 | int oldflags = ::fcntl(s, F_GETFL, 0); 149 | oldflags |= O_NONBLOCK; 150 | ::fcntl(s, F_SETFL, oldflags); 151 | #endif // _MSC_VER 152 | 153 | return s; 154 | } 155 | 156 | 157 | inline void close_socket(SOCKET s) 158 | { 159 | #ifdef _MSC_VER 160 | ::closesocket(s); 161 | #else 162 | ::close(s); 163 | #endif 164 | } 165 | 166 | inline int get_last_error() 167 | { 168 | #ifdef _MSC_VER 169 | return ::WSAGetLastError(); 170 | #else 171 | return errno; 172 | #endif 173 | } 174 | 175 | inline std::string get_host_ip_address(const char* host) 176 | { 177 | std::string ret; 178 | 179 | if (inet_addr(host) != -1) { 180 | ret.assign(host); 181 | return ret; 182 | } 183 | 184 | struct addrinfo hints, *res, *p; 185 | int status; 186 | char ipstr[INET6_ADDRSTRLEN] = { 0 }; 187 | 188 | memset(&hints, 0, sizeof hints); 189 | hints.ai_family = AF_UNSPEC; // AF_INET or AF_INET6 to force version 190 | hints.ai_socktype = SOCK_STREAM; 191 | 192 | if ((status = getaddrinfo(host, NULL, &hints, &res)) == 0) { 193 | for (p = res; p != NULL; p = p->ai_next) { 194 | void *addr; 195 | char *ipver; 196 | 197 | // get the pointer to the address itself, 198 | // different fields in IPv4 and IPv6: 199 | if (p->ai_family == AF_INET) { // IPv4 200 | struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr; 201 | addr = &(ipv4->sin_addr); 202 | //ipver = "IPv4"; 203 | } 204 | else { // IPv6 205 | struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr; 206 | addr = &(ipv6->sin6_addr); 207 | //ipver = "IPv6"; 208 | } 209 | 210 | // convert the IP to a string and print it: 211 | inet_ntop(p->ai_family, addr, ipstr, sizeof(ipstr)); 212 | ret.assign(ipstr); 213 | 214 | break; 215 | } 216 | } 217 | 218 | freeaddrinfo(res); // free the linked list 219 | 220 | return ret; 221 | } 222 | 223 | template 224 | void split_string(const std::string &src_str, OI oi) { 225 | std::string white_space_str = " \t\n\r\f"; 226 | 227 | std::string::size_type last_pos = 0; 228 | 229 | while (last_pos <= src_str.size()) { 230 | std::string::size_type pos; 231 | if ((last_pos = src_str.find_first_not_of(white_space_str, last_pos)) == std::string::npos) 232 | return; 233 | 234 | if ((pos = src_str.find_first_of(white_space_str, last_pos)) == std::string::npos) { 235 | *oi++ = src_str.substr(last_pos); 236 | return; 237 | } 238 | else { 239 | *oi++ = src_str.substr(last_pos, pos - last_pos); 240 | last_pos = pos; 241 | } 242 | } 243 | } 244 | -------------------------------------------------------------------------------- /example/rttp_asio_file_server.h: -------------------------------------------------------------------------------- 1 | #ifndef __RTTP_ASIO_FILE_SERVER__ 2 | #define __RTTP_ASIO_FILE_SERVER__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | using boost::asio::ip::udp; 29 | using namespace boost; 30 | using namespace std; 31 | 32 | class boost_rttp_server; 33 | class async_file_server; 34 | class async_file_operator; 35 | 36 | class client 37 | { 38 | public: 39 | virtual ~client() {} 40 | }; 41 | 42 | struct rtsocket_server_context 43 | { 44 | bool run = true; 45 | SOCKET socket = -1; 46 | uint64_t total_send = 0; 47 | uint64_t connection_num = 0; 48 | uint64_t total_waiting_send_num = 0; 49 | std::deque> udp_send_deq; 50 | std::deque> udp_recv_deq; 51 | 52 | char state[4096] = { 0 }; 53 | }; 54 | 55 | 56 | class async_file_handle 57 | { 58 | public: 59 | FILE* fp = NULL; 60 | uint64_t size = 0; 61 | time_t last_update = 0; 62 | std::set> operators; 63 | }; 64 | 65 | class async_file_operator 66 | { 67 | public: 68 | virtual void handle_open_file_complete(boost::shared_ptr handle_ptr, int err) = 0; 69 | virtual void handle_read_file_complete(char* buffer, int size) = 0; 70 | }; 71 | 72 | 73 | class async_file_server 74 | { 75 | public: 76 | async_file_server(asio::io_service& io_context); 77 | ~async_file_server(); 78 | 79 | void start(const char* path); 80 | void stop(); 81 | 82 | const std::string& work_path() const { return work_path_; } 83 | //uint64_t get_file_size(const std::string& file); 84 | 85 | void async_open_file(boost::shared_ptr initiator, const std::string& path_file, uint64_t offset = 0); 86 | void async_read_file(boost::shared_ptr initiator, boost::shared_ptr handle_ptr, uint64_t offset, char* buffer, int size); 87 | void async_close_file(boost::shared_ptr initiator, boost::shared_ptr handle_ptr); 88 | 89 | private: 90 | static int file_access_thread_proc(void* param); 91 | 92 | private: 93 | struct async_file_op 94 | { 95 | enum op_cmd { OPC_OPEN, OPC_READ, OPC_CLOSE, OPC_EXIT }; 96 | boost::shared_ptr initiator; 97 | boost::shared_ptr handle_ptr; 98 | int cmd; 99 | std::string file; 100 | uint64_t offset = 0; 101 | char* buffer = NULL; 102 | int size = 0; 103 | }; 104 | 105 | private: 106 | asio::io_service &io_context_; 107 | boost::lockfree::spsc_queue, boost::lockfree::capacity<256>> file_op_queue_; 108 | std::string work_path_; 109 | std::map> files_; 110 | 111 | boost::shared_ptr work_thread_ptr_; 112 | }; 113 | 114 | class client_factory 115 | { 116 | public: 117 | virtual boost::shared_ptr create_client(RTSOCKET socket, boost_rttp_server& server) = 0; 118 | virtual void close_client(boost::shared_ptr client_ptr) = 0; 119 | virtual boost::shared_ptr get_client(RTSOCKET socket) = 0; 120 | virtual std::vector> get_all_client() = 0; 121 | virtual std::vector get_all_socket() = 0; 122 | }; 123 | 124 | 125 | class download_file_client : public socket_io_info, public boost::enable_shared_from_this, public async_file_operator, public client 126 | { 127 | public: 128 | download_file_client(asio::io_service& io_ctx, boost_rttp_server& server, async_file_server& file_server, RTSOCKET socket); 129 | ~download_file_client(); 130 | 131 | void async_read_file(); 132 | void close(); 133 | 134 | virtual void handle_open_file_complete(boost::shared_ptr handle_ptr, int err); 135 | virtual void handle_read_file_complete(char* buffer, int size); 136 | 137 | public: 138 | std::string request_lines_; 139 | uint64_t req_file_pos_ = 0; 140 | uint64_t cur_file_pos_ = 0; 141 | bool reading_file_ = false; 142 | boost::shared_ptr handle_ptr_; 143 | 144 | uint64_t file_size_ = 0; 145 | //uint64_t sent_size_ = 0; 146 | asio::io_service& io_context_; 147 | RTSOCKET rttp_socket_; 148 | 149 | boost_rttp_server& rttp_server_; 150 | async_file_server& file_server_; 151 | 152 | }; 153 | 154 | class boost_rttp_server 155 | { 156 | public: 157 | boost_rttp_server(asio::io_service& io_context, short port, client_factory& clnt_factory); 158 | 159 | void do_receive(); 160 | void do_send(); 161 | 162 | void on_timer(system::error_code error); 163 | 164 | public: 165 | rtsocket_server_context server_ctx_; 166 | client_factory &client_factory_; 167 | private: 168 | udp::socket socket_; 169 | udp::endpoint sender_endpoint_; 170 | asio::io_service &io_context_; 171 | asio::steady_timer timer_; 172 | 173 | 174 | enum { max_length = 2048 }; 175 | char data_[max_length]; 176 | 177 | bool sending_ = false; 178 | char state[4096] = { 0 }; 179 | }; 180 | 181 | class download_file_client_factory : public client_factory 182 | { 183 | public: 184 | download_file_client_factory(asio::io_service& io_ctx, async_file_server& file_server); 185 | virtual ~download_file_client_factory(); 186 | 187 | virtual boost::shared_ptr create_client(RTSOCKET socket, boost_rttp_server& server); 188 | virtual void close_client(boost::shared_ptr client_ptr); 189 | virtual boost::shared_ptr get_client(RTSOCKET socket); 190 | virtual std::vector> get_all_client(); 191 | virtual std::vector get_all_socket(); 192 | private: 193 | asio::io_service& io_ctx_; 194 | async_file_server& file_server_; 195 | 196 | std::unordered_map> client_map_; 197 | }; 198 | 199 | #endif // !__RTTP_ASIO_FILE_SERVER__ 200 | -------------------------------------------------------------------------------- /spdlog/sinks/wincolor_sink-inl.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifndef SPDLOG_HEADER_ONLY 7 | #include "spdlog/sinks/wincolor_sink.h" 8 | #endif 9 | 10 | #include "spdlog/common.h" 11 | #include "spdlog/details/pattern_formatter.h" 12 | 13 | namespace spdlog { 14 | namespace sinks { 15 | 16 | template 17 | SPDLOG_INLINE wincolor_sink::wincolor_sink(HANDLE out_handle, color_mode mode) 18 | : out_handle_(out_handle) 19 | , mutex_(ConsoleMutex::mutex()) 20 | , formatter_(details::make_unique()) 21 | { 22 | // check if out_handle is points to the actual console. 23 | // ::GetConsoleMode() should return 0 if it is redirected or not valid console handle. 24 | DWORD console_mode; 25 | in_console_ = ::GetConsoleMode(out_handle, &console_mode) != 0; 26 | 27 | set_color_mode(mode); 28 | colors_[level::trace] = WHITE; 29 | colors_[level::debug] = CYAN; 30 | colors_[level::info] = GREEN; 31 | colors_[level::warn] = YELLOW | BOLD; 32 | colors_[level::err] = RED | BOLD; // red bold 33 | colors_[level::critical] = BACKGROUND_RED | WHITE | BOLD; // white bold on red background 34 | colors_[level::off] = 0; 35 | } 36 | 37 | template 38 | SPDLOG_INLINE wincolor_sink::~wincolor_sink() 39 | { 40 | this->flush(); 41 | } 42 | 43 | // change the color for the given level 44 | template 45 | void SPDLOG_INLINE wincolor_sink::set_color(level::level_enum level, WORD color) 46 | { 47 | std::lock_guard lock(mutex_); 48 | colors_[level] = color; 49 | } 50 | 51 | template 52 | void SPDLOG_INLINE wincolor_sink::log(const details::log_msg &msg) 53 | { 54 | std::lock_guard lock(mutex_); 55 | memory_buf_t formatted; 56 | formatter_->format(msg, formatted); 57 | if (!in_console_) 58 | { 59 | write_to_file_(formatted); 60 | return; 61 | } 62 | 63 | if (should_do_colors_ && msg.color_range_end > msg.color_range_start) 64 | { 65 | // before color range 66 | print_range_(formatted, 0, msg.color_range_start); 67 | 68 | // in color range 69 | auto orig_attribs = set_foreground_color_(colors_[msg.level]); 70 | print_range_(formatted, msg.color_range_start, msg.color_range_end); 71 | // reset to orig colors 72 | ::SetConsoleTextAttribute(out_handle_, orig_attribs); 73 | print_range_(formatted, msg.color_range_end, formatted.size()); 74 | } 75 | else // print without colors if color range is invalid (or color is disabled) 76 | { 77 | print_range_(formatted, 0, formatted.size()); 78 | } 79 | } 80 | 81 | template 82 | void SPDLOG_INLINE wincolor_sink::flush() 83 | { 84 | // windows console always flushed? 85 | } 86 | 87 | template 88 | void SPDLOG_INLINE wincolor_sink::set_pattern(const std::string &pattern) 89 | { 90 | std::lock_guard lock(mutex_); 91 | formatter_ = std::unique_ptr(new pattern_formatter(pattern)); 92 | } 93 | 94 | template 95 | void SPDLOG_INLINE wincolor_sink::set_formatter(std::unique_ptr sink_formatter) 96 | { 97 | std::lock_guard lock(mutex_); 98 | formatter_ = std::move(sink_formatter); 99 | } 100 | 101 | template 102 | void SPDLOG_INLINE wincolor_sink::set_color_mode(color_mode mode) 103 | { 104 | switch (mode) 105 | { 106 | case color_mode::always: 107 | case color_mode::automatic: 108 | should_do_colors_ = true; 109 | break; 110 | case color_mode::never: 111 | should_do_colors_ = false; 112 | break; 113 | default: 114 | should_do_colors_ = true; 115 | } 116 | } 117 | 118 | // set foreground color and return the orig console attributes (for resetting later) 119 | template 120 | WORD SPDLOG_INLINE wincolor_sink::set_foreground_color_(WORD attribs) 121 | { 122 | CONSOLE_SCREEN_BUFFER_INFO orig_buffer_info; 123 | ::GetConsoleScreenBufferInfo(out_handle_, &orig_buffer_info); 124 | WORD back_color = orig_buffer_info.wAttributes; 125 | // retrieve the current background color 126 | back_color &= static_cast(~(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY)); 127 | // keep the background color unchanged 128 | ::SetConsoleTextAttribute(out_handle_, attribs | back_color); 129 | return orig_buffer_info.wAttributes; // return orig attribs 130 | } 131 | 132 | // print a range of formatted message to console 133 | template 134 | void SPDLOG_INLINE wincolor_sink::print_range_(const memory_buf_t &formatted, size_t start, size_t end) 135 | { 136 | auto size = static_cast(end - start); 137 | ::WriteConsoleA(out_handle_, formatted.data() + start, size, nullptr, nullptr); 138 | } 139 | 140 | template 141 | void SPDLOG_INLINE wincolor_sink::write_to_file_(const memory_buf_t &formatted) 142 | { 143 | if(out_handle_ == nullptr) // no console and no file redirect 144 | { 145 | return; 146 | } 147 | auto size = static_cast(formatted.size()); 148 | if (size == 0) 149 | { 150 | return; 151 | } 152 | 153 | DWORD total_written = 0; 154 | do 155 | { 156 | DWORD bytes_written = 0; 157 | bool ok = ::WriteFile(out_handle_, formatted.data() + total_written, size - total_written, &bytes_written, nullptr) != 0; 158 | if (!ok || bytes_written == 0) 159 | { 160 | SPDLOG_THROW(spdlog_ex("wincolor_sink: write_to_file_ failed. GetLastError(): " + std::to_string(::GetLastError()))); 161 | } 162 | total_written += bytes_written; 163 | } while (total_written < size); 164 | } 165 | 166 | // wincolor_stdout_sink 167 | template 168 | SPDLOG_INLINE wincolor_stdout_sink::wincolor_stdout_sink(color_mode mode) 169 | : wincolor_sink(::GetStdHandle(STD_OUTPUT_HANDLE), mode) 170 | {} 171 | 172 | // wincolor_stderr_sink 173 | template 174 | SPDLOG_INLINE wincolor_stderr_sink::wincolor_stderr_sink(color_mode mode) 175 | : wincolor_sink(::GetStdHandle(STD_ERROR_HANDLE), mode) 176 | {} 177 | 178 | } // namespace sinks 179 | } // namespace spdlog 180 | -------------------------------------------------------------------------------- /spdlog/sinks/daily_file_sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include "spdlog/common.h" 7 | #include "spdlog/details/file_helper.h" 8 | #include "spdlog/details/null_mutex.h" 9 | #include "spdlog/fmt/fmt.h" 10 | #include "spdlog/sinks/base_sink.h" 11 | #include "spdlog/details/os.h" 12 | #include "spdlog/details/synchronous_factory.h" 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | namespace spdlog { 21 | namespace sinks { 22 | 23 | /* 24 | * Generator of daily log file names in format basename.YYYY-MM-DD.ext 25 | */ 26 | struct daily_filename_calculator 27 | { 28 | // Create filename for the form basename.YYYY-MM-DD 29 | static filename_t calc_filename(const filename_t &filename, const tm &now_tm) 30 | { 31 | filename_t basename, ext; 32 | std::tie(basename, ext) = details::file_helper::split_by_extension(filename); 33 | return fmt::format( 34 | SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}{}"), basename, now_tm.tm_year + 1900, now_tm.tm_mon + 1, now_tm.tm_mday, ext); 35 | } 36 | }; 37 | 38 | /* 39 | * Rotating file sink based on date. 40 | * If truncate != false , the created file will be truncated. 41 | * If max_files > 0, retain only the last max_files and delete previous. 42 | */ 43 | template 44 | class daily_file_sink final : public base_sink 45 | { 46 | public: 47 | // create daily file sink which rotates on given time 48 | daily_file_sink(filename_t base_filename, int rotation_hour, int rotation_minute, bool truncate = false, uint16_t max_files = 0) 49 | : base_filename_(std::move(base_filename)) 50 | , rotation_h_(rotation_hour) 51 | , rotation_m_(rotation_minute) 52 | , truncate_(truncate) 53 | , max_files_(max_files) 54 | , filenames_q_() 55 | { 56 | if (rotation_hour < 0 || rotation_hour > 23 || rotation_minute < 0 || rotation_minute > 59) 57 | { 58 | SPDLOG_THROW(spdlog_ex("daily_file_sink: Invalid rotation time in ctor")); 59 | } 60 | 61 | auto now = log_clock::now(); 62 | auto filename = FileNameCalc::calc_filename(base_filename_, now_tm(now)); 63 | file_helper_.open(filename, truncate_); 64 | rotation_tp_ = next_rotation_tp_(); 65 | 66 | if (max_files_ > 0) 67 | { 68 | filenames_q_ = details::circular_q(static_cast(max_files_)); 69 | filenames_q_.push_back(std::move(filename)); 70 | } 71 | } 72 | 73 | const filename_t &filename() const 74 | { 75 | return file_helper_.filename(); 76 | } 77 | 78 | protected: 79 | void sink_it_(const details::log_msg &msg) override 80 | { 81 | #ifdef SPDLOG_NO_DATETIME 82 | auto time = log_clock::now(); 83 | #else 84 | auto time = msg.time; 85 | #endif 86 | 87 | bool should_rotate = time >= rotation_tp_; 88 | if (should_rotate) 89 | { 90 | auto filename = FileNameCalc::calc_filename(base_filename_, now_tm(time)); 91 | file_helper_.open(filename, truncate_); 92 | rotation_tp_ = next_rotation_tp_(); 93 | } 94 | memory_buf_t formatted; 95 | base_sink::formatter_->format(msg, formatted); 96 | file_helper_.write(formatted); 97 | 98 | // Do the cleaning ony at the end because it might throw on failure. 99 | if (should_rotate && max_files_ > 0) 100 | { 101 | delete_old_(); 102 | } 103 | } 104 | 105 | void flush_() override 106 | { 107 | file_helper_.flush(); 108 | } 109 | 110 | private: 111 | tm now_tm(log_clock::time_point tp) 112 | { 113 | time_t tnow = log_clock::to_time_t(tp); 114 | return spdlog::details::os::localtime(tnow); 115 | } 116 | 117 | log_clock::time_point next_rotation_tp_() 118 | { 119 | auto now = log_clock::now(); 120 | tm date = now_tm(now); 121 | date.tm_hour = rotation_h_; 122 | date.tm_min = rotation_m_; 123 | date.tm_sec = 0; 124 | auto rotation_time = log_clock::from_time_t(std::mktime(&date)); 125 | if (rotation_time > now) 126 | { 127 | return rotation_time; 128 | } 129 | return {rotation_time + std::chrono::hours(24)}; 130 | } 131 | 132 | // Delete the file N rotations ago. 133 | // Throw spdlog_ex on failure to delete the old file. 134 | void delete_old_() 135 | { 136 | using details::os::filename_to_str; 137 | using details::os::remove_if_exists; 138 | 139 | filename_t current_file = filename(); 140 | if (filenames_q_.full()) 141 | { 142 | auto old_filename = std::move(filenames_q_.front()); 143 | filenames_q_.pop_front(); 144 | bool ok = remove_if_exists(old_filename) == 0; 145 | if (!ok) 146 | { 147 | filenames_q_.push_back(std::move(current_file)); 148 | SPDLOG_THROW(spdlog_ex("Failed removing daily file " + filename_to_str(old_filename), errno)); 149 | } 150 | } 151 | filenames_q_.push_back(std::move(current_file)); 152 | } 153 | 154 | filename_t base_filename_; 155 | int rotation_h_; 156 | int rotation_m_; 157 | log_clock::time_point rotation_tp_; 158 | details::file_helper file_helper_; 159 | bool truncate_; 160 | uint16_t max_files_; 161 | details::circular_q filenames_q_; 162 | }; 163 | 164 | using daily_file_sink_mt = daily_file_sink; 165 | using daily_file_sink_st = daily_file_sink; 166 | 167 | } // namespace sinks 168 | 169 | // 170 | // factory functions 171 | // 172 | template 173 | inline std::shared_ptr daily_logger_mt( 174 | const std::string &logger_name, const filename_t &filename, int hour = 0, int minute = 0, bool truncate = false) 175 | { 176 | return Factory::template create(logger_name, filename, hour, minute, truncate); 177 | } 178 | 179 | template 180 | inline std::shared_ptr daily_logger_st( 181 | const std::string &logger_name, const filename_t &filename, int hour = 0, int minute = 0, bool truncate = false) 182 | { 183 | return Factory::template create(logger_name, filename, hour, minute, truncate); 184 | } 185 | } // namespace spdlog 186 | -------------------------------------------------------------------------------- /spdlog/tweakme.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | /////////////////////////////////////////////////////////////////////////////// 7 | // 8 | // Edit this file to squeeze more performance, and to customize supported 9 | // features 10 | // 11 | /////////////////////////////////////////////////////////////////////////////// 12 | 13 | /////////////////////////////////////////////////////////////////////////////// 14 | // Under Linux, the much faster CLOCK_REALTIME_COARSE clock can be used. 15 | // This clock is less accurate - can be off by dozens of millis - depending on 16 | // the kernel HZ. 17 | // Uncomment to use it instead of the regular clock. 18 | // 19 | // #define SPDLOG_CLOCK_COARSE 20 | /////////////////////////////////////////////////////////////////////////////// 21 | 22 | /////////////////////////////////////////////////////////////////////////////// 23 | // Uncomment if date/time logging is not needed and never appear in the log 24 | // pattern. 25 | // This will prevent spdlog from querying the clock on each log call. 26 | // 27 | // WARNING: If the log pattern contains any date/time while this flag is on, the 28 | // result is undefined. 29 | // You must set new pattern(spdlog::set_pattern(..") without any 30 | // date/time in it 31 | // 32 | // #define SPDLOG_NO_DATETIME 33 | /////////////////////////////////////////////////////////////////////////////// 34 | 35 | /////////////////////////////////////////////////////////////////////////////// 36 | // Uncomment if thread id logging is not needed (i.e. no %t in the log pattern). 37 | // This will prevent spdlog from querying the thread id on each log call. 38 | // 39 | // WARNING: If the log pattern contains thread id (i.e, %t) while this flag is 40 | // on, the result is undefined. 41 | // 42 | // #define SPDLOG_NO_THREAD_ID 43 | /////////////////////////////////////////////////////////////////////////////// 44 | 45 | /////////////////////////////////////////////////////////////////////////////// 46 | // Uncomment to prevent spdlog from using thread local storage. 47 | // 48 | // WARNING: if your program forks, UNCOMMENT this flag to prevent undefined 49 | // thread ids in the children logs. 50 | // 51 | // #define SPDLOG_NO_TLS 52 | /////////////////////////////////////////////////////////////////////////////// 53 | 54 | /////////////////////////////////////////////////////////////////////////////// 55 | // Uncomment if logger name logging is not needed. 56 | // This will prevent spdlog from copying the logger name on each log call. 57 | // 58 | // #define SPDLOG_NO_NAME 59 | /////////////////////////////////////////////////////////////////////////////// 60 | 61 | /////////////////////////////////////////////////////////////////////////////// 62 | // Uncomment to avoid spdlog's usage of atomic log levels 63 | // Use only if your code never modifies a logger's log levels concurrently by 64 | // different threads. 65 | // 66 | // #define SPDLOG_NO_ATOMIC_LEVELS 67 | /////////////////////////////////////////////////////////////////////////////// 68 | 69 | /////////////////////////////////////////////////////////////////////////////// 70 | // Uncomment to enable usage of wchar_t for file names on Windows. 71 | // 72 | // #define SPDLOG_WCHAR_FILENAMES 73 | /////////////////////////////////////////////////////////////////////////////// 74 | 75 | /////////////////////////////////////////////////////////////////////////////// 76 | // Uncomment to override default eol ("\n" or "\r\n" under Linux/Windows) 77 | // 78 | // #define SPDLOG_EOL ";-)\n" 79 | /////////////////////////////////////////////////////////////////////////////// 80 | 81 | /////////////////////////////////////////////////////////////////////////////// 82 | // Uncomment to use your own copy of the fmt library instead of spdlog's copy. 83 | // In this case spdlog will try to include so set your -I flag 84 | // accordingly. 85 | // 86 | // #define SPDLOG_FMT_EXTERNAL 87 | /////////////////////////////////////////////////////////////////////////////// 88 | 89 | /////////////////////////////////////////////////////////////////////////////// 90 | // Uncomment to enable wchar_t support (convert to utf8) 91 | // 92 | // #define SPDLOG_WCHAR_TO_UTF8_SUPPORT 93 | /////////////////////////////////////////////////////////////////////////////// 94 | 95 | /////////////////////////////////////////////////////////////////////////////// 96 | // Uncomment to prevent child processes from inheriting log file descriptors 97 | // 98 | // #define SPDLOG_PREVENT_CHILD_FD 99 | /////////////////////////////////////////////////////////////////////////////// 100 | 101 | /////////////////////////////////////////////////////////////////////////////// 102 | // Uncomment to customize level names (e.g. "MT TRACE") 103 | // 104 | // #define SPDLOG_LEVEL_NAMES { "MY TRACE", "MY DEBUG", "MY INFO", "MY WARNING", 105 | // "MY ERROR", "MY CRITICAL", "OFF" } 106 | /////////////////////////////////////////////////////////////////////////////// 107 | 108 | /////////////////////////////////////////////////////////////////////////////// 109 | // Uncomment to customize short level names (e.g. "MT") 110 | // These can be longer than one character. 111 | // 112 | // #define SPDLOG_SHORT_LEVEL_NAMES { "T", "D", "I", "W", "E", "C", "O" } 113 | /////////////////////////////////////////////////////////////////////////////// 114 | 115 | /////////////////////////////////////////////////////////////////////////////// 116 | // Uncomment to disable default logger creation. 117 | // This might save some (very) small initialization time if no default logger is needed. 118 | // 119 | // #define SPDLOG_DISABLE_DEFAULT_LOGGER 120 | /////////////////////////////////////////////////////////////////////////////// 121 | 122 | /////////////////////////////////////////////////////////////////////////////// 123 | // Uncomment and set to compile time level with zero cost (default is INFO). 124 | // Macros like SPDLOG_DEBUG(..), SPDLOG_INFO(..) will expand to empty statements if not enabled 125 | // 126 | // #define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_INFO 127 | /////////////////////////////////////////////////////////////////////////////// 128 | 129 | /////////////////////////////////////////////////////////////////////////////// 130 | // Uncomment (and change if desired) macro to use for function names. 131 | // This is compiler dependent. 132 | // __PRETTY_FUNCTION__ might be nicer in clang/gcc, and __FUNCTION__ in msvc. 133 | // Defaults to __FUNCTION__ (should work on all compilers) if not defined. 134 | // 135 | // #define SPDLOG_FUNCTION __PRETTY_FUNCTION__ 136 | /////////////////////////////////////////////////////////////////////////////// 137 | -------------------------------------------------------------------------------- /spdlog/logger-inl.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifndef SPDLOG_HEADER_ONLY 7 | #include "spdlog/logger.h" 8 | #endif 9 | 10 | #include "spdlog/sinks/sink.h" 11 | #include "spdlog/details/backtracer.h" 12 | #include "spdlog/details/pattern_formatter.h" 13 | 14 | #include 15 | 16 | namespace spdlog { 17 | 18 | // public methods 19 | SPDLOG_INLINE logger::logger(const logger &other) 20 | : name_(other.name_) 21 | , sinks_(other.sinks_) 22 | , level_(other.level_.load(std::memory_order_relaxed)) 23 | , flush_level_(other.flush_level_.load(std::memory_order_relaxed)) 24 | , custom_err_handler_(other.custom_err_handler_) 25 | , tracer_(other.tracer_) 26 | {} 27 | 28 | SPDLOG_INLINE logger::logger(logger &&other) SPDLOG_NOEXCEPT : name_(std::move(other.name_)), 29 | sinks_(std::move(other.sinks_)), 30 | level_(other.level_.load(std::memory_order_relaxed)), 31 | flush_level_(other.flush_level_.load(std::memory_order_relaxed)), 32 | custom_err_handler_(std::move(other.custom_err_handler_)), 33 | tracer_(std::move(other.tracer_)) 34 | 35 | {} 36 | 37 | SPDLOG_INLINE logger &logger::operator=(logger other) SPDLOG_NOEXCEPT 38 | { 39 | this->swap(other); 40 | return *this; 41 | } 42 | 43 | SPDLOG_INLINE void logger::swap(spdlog::logger &other) SPDLOG_NOEXCEPT 44 | { 45 | name_.swap(other.name_); 46 | sinks_.swap(other.sinks_); 47 | 48 | // swap level_ 49 | auto other_level = other.level_.load(); 50 | auto my_level = level_.exchange(other_level); 51 | other.level_.store(my_level); 52 | 53 | // swap flush level_ 54 | other_level = other.flush_level_.load(); 55 | my_level = flush_level_.exchange(other_level); 56 | other.flush_level_.store(my_level); 57 | 58 | custom_err_handler_.swap(other.custom_err_handler_); 59 | std::swap(tracer_, other.tracer_); 60 | } 61 | 62 | SPDLOG_INLINE void swap(logger &a, logger &b) 63 | { 64 | a.swap(b); 65 | } 66 | 67 | SPDLOG_INLINE bool logger::should_log(level::level_enum msg_level) const 68 | { 69 | return msg_level >= level_.load(std::memory_order_relaxed); 70 | } 71 | 72 | SPDLOG_INLINE void logger::set_level(level::level_enum log_level) 73 | { 74 | level_.store(log_level); 75 | } 76 | 77 | SPDLOG_INLINE level::level_enum logger::level() const 78 | { 79 | return static_cast(level_.load(std::memory_order_relaxed)); 80 | } 81 | 82 | SPDLOG_INLINE const std::string &logger::name() const 83 | { 84 | return name_; 85 | } 86 | 87 | // set formatting for the sinks in this logger. 88 | // each sink will get a seperate instance of the formatter object. 89 | SPDLOG_INLINE void logger::set_formatter(std::unique_ptr f) 90 | { 91 | for (auto it = sinks_.begin(); it != sinks_.end(); ++it) 92 | { 93 | if (std::next(it) == sinks_.end()) 94 | { 95 | // last element - we can be move it. 96 | (*it)->set_formatter(std::move(f)); 97 | } 98 | else 99 | { 100 | (*it)->set_formatter(f->clone()); 101 | } 102 | } 103 | } 104 | 105 | SPDLOG_INLINE void logger::set_pattern(std::string pattern, pattern_time_type time_type) 106 | { 107 | auto new_formatter = details::make_unique(std::move(pattern), time_type); 108 | set_formatter(std::move(new_formatter)); 109 | } 110 | 111 | // create new backtrace sink and move to it all our child sinks 112 | SPDLOG_INLINE void logger::enable_backtrace(size_t n_messages) 113 | { 114 | tracer_.enable(n_messages); 115 | } 116 | 117 | // restore orig sinks and level and delete the backtrace sink 118 | SPDLOG_INLINE void logger::disable_backtrace() 119 | { 120 | tracer_.disable(); 121 | } 122 | 123 | SPDLOG_INLINE void logger::dump_backtrace() 124 | { 125 | dump_backtrace_(); 126 | } 127 | 128 | // flush functions 129 | SPDLOG_INLINE void logger::flush() 130 | { 131 | flush_(); 132 | } 133 | 134 | SPDLOG_INLINE void logger::flush_on(level::level_enum log_level) 135 | { 136 | flush_level_.store(log_level); 137 | } 138 | 139 | SPDLOG_INLINE level::level_enum logger::flush_level() const 140 | { 141 | return static_cast(flush_level_.load(std::memory_order_relaxed)); 142 | } 143 | 144 | // sinks 145 | SPDLOG_INLINE const std::vector &logger::sinks() const 146 | { 147 | return sinks_; 148 | } 149 | 150 | SPDLOG_INLINE std::vector &logger::sinks() 151 | { 152 | return sinks_; 153 | } 154 | 155 | // error handler 156 | SPDLOG_INLINE void logger::set_error_handler(err_handler handler) 157 | { 158 | custom_err_handler_ = handler; 159 | } 160 | 161 | // create new logger with same sinks and configuration. 162 | SPDLOG_INLINE std::shared_ptr logger::clone(std::string logger_name) 163 | { 164 | auto cloned = std::make_shared(*this); 165 | cloned->name_ = std::move(logger_name); 166 | return cloned; 167 | } 168 | 169 | // protected methods 170 | SPDLOG_INLINE void logger::sink_it_(const details::log_msg &msg) 171 | { 172 | for (auto &sink : sinks_) 173 | { 174 | if (sink->should_log(msg.level)) 175 | { 176 | SPDLOG_TRY 177 | { 178 | sink->log(msg); 179 | } 180 | SPDLOG_LOGGER_CATCH() 181 | } 182 | } 183 | 184 | if (should_flush_(msg)) 185 | { 186 | flush_(); 187 | } 188 | } 189 | 190 | SPDLOG_INLINE void logger::flush_() 191 | { 192 | for (auto &sink : sinks_) 193 | { 194 | SPDLOG_TRY 195 | { 196 | sink->flush(); 197 | } 198 | SPDLOG_LOGGER_CATCH() 199 | } 200 | } 201 | 202 | SPDLOG_INLINE void logger::dump_backtrace_() 203 | { 204 | using details::log_msg; 205 | if (tracer_) 206 | { 207 | sink_it_(log_msg{name(), level::info, "****************** Backtrace Start ******************"}); 208 | tracer_.foreach_pop([this](const log_msg &msg) { this->sink_it_(msg); }); 209 | sink_it_(log_msg{name(), level::info, "****************** Backtrace End ********************"}); 210 | } 211 | } 212 | 213 | SPDLOG_INLINE bool logger::should_flush_(const details::log_msg &msg) 214 | { 215 | auto flush_level = flush_level_.load(std::memory_order_relaxed); 216 | return (msg.level >= flush_level) && (msg.level != level::off); 217 | } 218 | 219 | SPDLOG_INLINE void logger::err_handler_(const std::string &msg) 220 | { 221 | if (custom_err_handler_) 222 | { 223 | custom_err_handler_(msg); 224 | } 225 | else 226 | { 227 | using std::chrono::system_clock; 228 | static std::mutex mutex; 229 | static std::chrono::system_clock::time_point last_report_time; 230 | static size_t err_counter = 0; 231 | std::lock_guard lk{mutex}; 232 | auto now = system_clock::now(); 233 | err_counter++; 234 | if (now - last_report_time < std::chrono::seconds(1)) 235 | { 236 | return; 237 | } 238 | last_report_time = now; 239 | auto tm_time = details::os::localtime(system_clock::to_time_t(now)); 240 | char date_buf[64]; 241 | std::strftime(date_buf, sizeof(date_buf), "%Y-%m-%d %H:%M:%S", &tm_time); 242 | fprintf(stderr, "[*** LOG ERROR #%04zu ***] [%s] [%s] {%s}\n", err_counter, date_buf, name().c_str(), msg.c_str()); 243 | } 244 | } 245 | } // namespace spdlog 246 | -------------------------------------------------------------------------------- /spdlog/common.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include "spdlog/tweakme.h" 7 | #include "spdlog/details/null_mutex.h" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #ifdef _WIN32 19 | #ifndef NOMINMAX 20 | #define NOMINMAX // prevent windows redefining min/max 21 | #endif 22 | 23 | #ifndef WIN32_LEAN_AND_MEAN 24 | #define WIN32_LEAN_AND_MEAN 25 | #endif 26 | 27 | #include 28 | #endif //_WIN32 29 | 30 | #ifdef SPDLOG_COMPILED_LIB 31 | #undef SPDLOG_HEADER_ONLY 32 | #define SPDLOG_INLINE 33 | #else 34 | #define SPDLOG_HEADER_ONLY 35 | #define SPDLOG_INLINE inline 36 | #endif 37 | 38 | #include "spdlog/fmt/fmt.h" 39 | 40 | // visual studio upto 2013 does not support noexcept nor constexpr 41 | #if defined(_MSC_VER) && (_MSC_VER < 1900) 42 | #define SPDLOG_NOEXCEPT _NOEXCEPT 43 | #define SPDLOG_CONSTEXPR 44 | #else 45 | #define SPDLOG_NOEXCEPT noexcept 46 | #define SPDLOG_CONSTEXPR constexpr 47 | #endif 48 | 49 | #if defined(__GNUC__) || defined(__clang__) 50 | #define SPDLOG_DEPRECATED __attribute__((deprecated)) 51 | #elif defined(_MSC_VER) 52 | #define SPDLOG_DEPRECATED __declspec(deprecated) 53 | #else 54 | #define SPDLOG_DEPRECATED 55 | #endif 56 | 57 | // disable thread local on msvc 2013 58 | #ifndef SPDLOG_NO_TLS 59 | #if (defined(_MSC_VER) && (_MSC_VER < 1900)) || defined(__cplusplus_winrt) 60 | #define SPDLOG_NO_TLS 1 61 | #endif 62 | #endif 63 | 64 | #ifndef SPDLOG_FUNCTION 65 | #define SPDLOG_FUNCTION __FUNCTION__ 66 | #endif 67 | 68 | #ifdef SPDLOG_NO_EXCEPTIONS 69 | #define SPDLOG_TRY 70 | #define SPDLOG_THROW(ex) \ 71 | do \ 72 | { \ 73 | printf("spdlog fatal error: %s\n", ex.what()); \ 74 | std::abort(); \ 75 | } while (0) 76 | #define SPDLOG_CATCH_ALL() 77 | #else 78 | #define SPDLOG_TRY try 79 | #define SPDLOG_THROW(ex) throw(ex) 80 | #define SPDLOG_CATCH_ALL() catch (...) 81 | #endif 82 | 83 | namespace spdlog { 84 | 85 | class formatter; 86 | 87 | namespace sinks { 88 | class sink; 89 | } 90 | 91 | #if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES) 92 | using filename_t = std::wstring; 93 | #define SPDLOG_FILENAME_T(s) L##s 94 | #else 95 | using filename_t = std::string; 96 | #define SPDLOG_FILENAME_T(s) s 97 | #endif 98 | 99 | using log_clock = std::chrono::system_clock; 100 | using sink_ptr = std::shared_ptr; 101 | using sinks_init_list = std::initializer_list; 102 | using err_handler = std::function; 103 | using string_view_t = fmt::basic_string_view; 104 | using wstring_view_t = fmt::basic_string_view; 105 | using memory_buf_t = fmt::basic_memory_buffer; 106 | 107 | #ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT 108 | #ifndef _WIN32 109 | #error SPDLOG_WCHAR_TO_UTF8_SUPPORT only supported on windows 110 | #else 111 | template 112 | struct is_convertible_to_wstring_view : std::is_convertible 113 | {}; 114 | #endif // _WIN32 115 | #else 116 | template 117 | struct is_convertible_to_wstring_view : std::false_type 118 | {}; 119 | #endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT 120 | 121 | #if defined(SPDLOG_NO_ATOMIC_LEVELS) 122 | using level_t = details::null_atomic_int; 123 | #else 124 | using level_t = std::atomic; 125 | #endif 126 | 127 | #define SPDLOG_LEVEL_TRACE 0 128 | #define SPDLOG_LEVEL_DEBUG 1 129 | #define SPDLOG_LEVEL_INFO 2 130 | #define SPDLOG_LEVEL_WARN 3 131 | #define SPDLOG_LEVEL_ERROR 4 132 | #define SPDLOG_LEVEL_CRITICAL 5 133 | #define SPDLOG_LEVEL_OFF 6 134 | 135 | #if !defined(SPDLOG_ACTIVE_LEVEL) 136 | #define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_INFO 137 | #endif 138 | 139 | // Log level enum 140 | namespace level { 141 | enum level_enum 142 | { 143 | trace = SPDLOG_LEVEL_TRACE, 144 | debug = SPDLOG_LEVEL_DEBUG, 145 | info = SPDLOG_LEVEL_INFO, 146 | warn = SPDLOG_LEVEL_WARN, 147 | err = SPDLOG_LEVEL_ERROR, 148 | critical = SPDLOG_LEVEL_CRITICAL, 149 | off = SPDLOG_LEVEL_OFF, 150 | }; 151 | 152 | #if !defined(SPDLOG_LEVEL_NAMES) 153 | #define SPDLOG_LEVEL_NAMES \ 154 | { \ 155 | "trace", "debug", "info", "warning", "error", "critical", "off" \ 156 | } 157 | #endif 158 | 159 | #if !defined(SPDLOG_SHORT_LEVEL_NAMES) 160 | 161 | #define SPDLOG_SHORT_LEVEL_NAMES \ 162 | { \ 163 | "T", "D", "I", "W", "E", "C", "O" \ 164 | } 165 | #endif 166 | 167 | string_view_t &to_string_view(spdlog::level::level_enum l) SPDLOG_NOEXCEPT; 168 | const char *to_short_c_str(spdlog::level::level_enum l) SPDLOG_NOEXCEPT; 169 | spdlog::level::level_enum from_str(const std::string &name) SPDLOG_NOEXCEPT; 170 | 171 | using level_hasher = std::hash; 172 | } // namespace level 173 | 174 | // 175 | // Color mode used by sinks with color support. 176 | // 177 | enum class color_mode 178 | { 179 | always, 180 | automatic, 181 | never 182 | }; 183 | 184 | // 185 | // Pattern time - specific time getting to use for pattern_formatter. 186 | // local time by default 187 | // 188 | enum class pattern_time_type 189 | { 190 | local, // log localtime 191 | utc // log utc 192 | }; 193 | 194 | // 195 | // Log exception 196 | // 197 | class spdlog_ex : public std::exception 198 | { 199 | public: 200 | explicit spdlog_ex(std::string msg); 201 | spdlog_ex(const std::string &msg, int last_errno); 202 | const char *what() const SPDLOG_NOEXCEPT override; 203 | 204 | private: 205 | std::string msg_; 206 | }; 207 | 208 | struct source_loc 209 | { 210 | SPDLOG_CONSTEXPR source_loc() = default; 211 | SPDLOG_CONSTEXPR source_loc(const char *filename_in, int line_in, const char *funcname_in) 212 | : filename{filename_in} 213 | , line{line_in} 214 | , funcname{funcname_in} 215 | {} 216 | 217 | SPDLOG_CONSTEXPR bool empty() const SPDLOG_NOEXCEPT 218 | { 219 | return line == 0; 220 | } 221 | const char *filename{nullptr}; 222 | int line{0}; 223 | const char *funcname{nullptr}; 224 | }; 225 | 226 | namespace details { 227 | // make_unique support for pre c++14 228 | 229 | #if __cplusplus >= 201402L // C++14 and beyond 230 | using std::make_unique; 231 | #else 232 | template 233 | std::unique_ptr make_unique(Args &&... args) 234 | { 235 | static_assert(!std::is_array::value, "arrays not supported"); 236 | return std::unique_ptr(new T(std::forward(args)...)); 237 | } 238 | #endif 239 | } // namespace details 240 | 241 | } // namespace spdlog 242 | 243 | #ifdef SPDLOG_HEADER_ONLY 244 | #include "common-inl.h" 245 | #endif 246 | -------------------------------------------------------------------------------- /utp_socket.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "congestion_control.h" 10 | #include "round_trip_meter.h" 11 | #include "utp_socket_c.h" 12 | #include "trip_time_sample.h" 13 | #include "utp_common.h" 14 | 15 | #ifdef _MSC_VER 16 | #include 17 | #else 18 | #include 19 | #endif // _MSC_ 20 | 21 | namespace rtttech_utp 22 | { 23 | 24 | enum RTSocketState { RTSS_IDLE, RTSS_SYN_SENT, RTSS_SYN_RECEIVED, RTSS_ESTABLISHED, RTSS_CLOSING, RTSS_CLOSE_WAIT, RTSS_CLOSED, RTSS_ERROR }; 25 | 26 | //enum RTCommand { RTC_SYN, RTC_SYN_ACK, RTC_DATA, RTC_ACK, RTC_CLOSE, RTC_RESET, RTC_FEC }; 27 | 28 | enum FECType { FECT_XOR }; 29 | 30 | enum RTCommand { 31 | RTC_DATA = 0, // Data packet. 32 | RTC_FIN = 1, // Finalize the connection. This is the last packet. 33 | RTC_STATE = 2, // State packet. Used to transmit an ACK with no data. 34 | RTC_RESET = 3, // Terminate connection forcefully. 35 | RTC_SYN = 4, // Connect SYN 36 | RTC_NUM_STATES, // used for bounds checking 37 | }; 38 | 39 | enum { 40 | EXT_SACK = 1 41 | }; 42 | 43 | const uint8_t UTP_VER = 1; 44 | 45 | #if (defined(__SVR4) && defined(__sun)) 46 | #pragma pack(1) 47 | #else 48 | #pragma pack(push,1) 49 | #endif 50 | /* 51 | uTP header from BEP 29 52 | 0 4 8 16 24 32 53 | +-------+-------+---------------+---------------+---------------+ 54 | | type | ver | extension | connection_id | 55 | +-------+-------+---------------+---------------+---------------+ 56 | | timestamp_microseconds | 57 | +---------------+---------------+---------------+---------------+ 58 | | timestamp_difference_microseconds | 59 | +---------------+---------------+---------------+---------------+ 60 | | wnd_size | 61 | +---------------+---------------+---------------+---------------+ 62 | | seq_nr | ack_nr | 63 | +---------------+---------------+---------------+---------------+ 64 | */ 65 | 66 | struct UTPHeader 67 | { 68 | std::uint8_t type_ver; 69 | std::uint8_t extension; 70 | std::uint16_t conn_id; 71 | std::uint32_t timestamp; 72 | std::uint32_t timestamp_difference; 73 | std::uint32_t recv_wnd; 74 | std::uint16_t pkt_seq; 75 | std::uint16_t ack_pkt_seq; 76 | 77 | int GetType() const { return type_ver >> 4; } 78 | void SetType(uint8_t t) { type_ver = (type_ver & 0xf) | (t << 4); } 79 | 80 | int GetVersion() const { return type_ver & 0xf; } 81 | void SetVersion(uint8_t v) { type_ver = (type_ver & 0xf0) | (v & 0xf); } 82 | }; 83 | 84 | typedef UTPHeader PacketHead; 85 | 86 | struct PacketHeadAck { 87 | PacketHead pf; 88 | std::uint8_t ext_next; 89 | std::uint8_t ext_len; 90 | std::uint8_t acks[4]; 91 | }; 92 | 93 | 94 | #if (defined(__SVR4) && defined(__sun)) 95 | #pragma pack(0) 96 | #else 97 | #pragma pack(pop) 98 | #endif 99 | 100 | void HeaderToBigEndian(PacketHead* pHead); 101 | 102 | struct PacketCS 103 | { 104 | PacketCS() : buffer(NULL), len(0), pos(0), send_time(0), resend_times(0), ack_time(0), 105 | fec_sent(false), pkt_data_bytes(0), pkt_seq(0), wanted_times(0) {} 106 | ~PacketCS() { if (buffer) { delete[] buffer; buffer = NULL; } } 107 | 108 | char *buffer; 109 | int32_t len; 110 | int32_t pos; 111 | int64_t send_time; 112 | int64_t ack_time; 113 | int32_t resend_times; 114 | int32_t wanted_times; 115 | uint16_t pkt_seq; 116 | int32_t pkt_data_bytes; 117 | int32_t pkt_head_len; 118 | int32_t pkt_bitmap_bytes; 119 | uint8_t pkt_cmd; 120 | bool fec_sent; 121 | 122 | std::string Desc() const 123 | { 124 | std::ostringstream oss; 125 | oss << "pkt_seq:" << pkt_seq; 126 | oss << "len:" << len; 127 | oss << "send_time:" << send_time; 128 | oss << "ack_time:" << ack_time; 129 | oss << "resend_times:" << resend_times; 130 | oss << "wanted_times:" << wanted_times; 131 | 132 | return oss.str(); 133 | } 134 | }; 135 | 136 | class UTPSocket 137 | { 138 | public: 139 | UTPSocket(socket_event_callback *cb, send_data_callback *pfsend, UTPClock* clock, bool passive = false); 140 | virtual ~UTPSocket(); 141 | 142 | int Connect(const char *to, int tolen); 143 | int Recv(char * buffer, int len, int flag); 144 | int Send(const char * buffer, int len, int flag); 145 | void Close(); 146 | 147 | void OnTick(); 148 | int OnPacket(const char* buffer, int len, const char *from, int from_len); 149 | 150 | inline RTSocketState State() const { return m_eState; } 151 | 152 | uint16_t GetConnID() const { return m_nConnID; } 153 | void SetConnID(uint16_t connid) { m_nConnID = connid; } 154 | 155 | bool IsReadable(); 156 | bool IsWritable(); 157 | bool IsConnected(); 158 | int GetError(); 159 | 160 | bool IsPassive() const { return m_bPassive; } 161 | 162 | const std::string& GetRemoteAddr() const { return m_strRemoteAddr; } 163 | 164 | inline bool IsDestroyed() const { return m_bDestroyed && (m_eState == RTSS_CLOSED || m_eState == RTSS_ERROR) ; } 165 | 166 | int SetSockOpt(int optname, void *optval, int optlen); 167 | int GetSockOpt(int optname, void *optval, int optlen); 168 | 169 | void SetUserData(void* userdata); 170 | void* GetUserData(); 171 | 172 | std::string GetInternalState(); 173 | public: 174 | static uint32_t s_nTotalTickTakeTime; 175 | private: 176 | int FillPacketHead(PacketHead* pHeader, RTCommand cmd, int nDataBytes, int nBitmapBytes); 177 | 178 | void ChangeToState(RTSocketState s); 179 | 180 | int DoSendData(char* buffer, int len, bool withack); 181 | 182 | int SendSyn(bool ack = false); 183 | int SendData(const char * buffer, int len, int flag); 184 | int SendState(); 185 | int SendClose(bool resp = false); 186 | int SendReset(); 187 | 188 | void ClearConnection(); 189 | 190 | void OnSyn(const PacketHead *pHeader, int nPktLen); 191 | void OnState(const PacketHead *pHeader, int nPktLen); 192 | void OnData(const PacketHead *pHeader, int nPktLen); 193 | void OnClose(const PacketHead *pHeader, int nPktLen); 194 | void OnReset(const PacketHead *pHeader, int nPktLen); 195 | 196 | int OnAck(const PacketHead *pHeader, int nPktLen); 197 | 198 | bool SaveReceivedData(std::shared_ptr pkt, CircleSeq pkt_seq, int len); 199 | 200 | bool IsPacketValid(const PacketHead* pHeader); 201 | uint32_t GetLeftSendWndBytes(); 202 | uint32_t GetLeftRecvWndBytes(); 203 | 204 | int ResendPacket(PacketCS &pkt); 205 | 206 | int GetAllowWriteBytes(); 207 | 208 | uint32_t GetAckInterval(); 209 | 210 | private: 211 | bool m_bPassive; 212 | bool m_bDestroyed; 213 | socket_event_callback *m_pfCallBack; 214 | send_data_callback *m_pfSendProc; 215 | void* m_pUserdata; 216 | 217 | int m_nError; 218 | std::string m_strRemoteAddr; 219 | 220 | RTSocketState m_eState; 221 | uint64_t m_nStateChangeTime; 222 | 223 | CircleSeq m_nLocalSendPktSeq, m_nLocalExpectPktSeq, m_nRemoteAckedPktSeq, m_nRemoteExpectBytesSeq; 224 | CircleSeq m_nLocalSendBytesSeq, m_nLocalExpectBytesSeq; 225 | CircleSeq m_nSendSeq;// 226 | 227 | uint16_t m_nMtu; 228 | uint32_t m_nRemoteRecvWnd, m_nLocalRecvWnd; 229 | int32_t m_nReadableBytes; 230 | int32_t m_nNotReadableBytes; 231 | 232 | int32_t m_nNotAckedDataBytes; 233 | uint16_t m_nConnID; 234 | 235 | uint64_t m_nLastReceivedTime; 236 | uint64_t m_nConnTimeoutTime; 237 | uint64_t m_nLastSendAck; 238 | uint32_t m_nAckInterval; 239 | uint64_t m_nLastSendFec; 240 | 241 | uint64_t m_nTotalPktNum; 242 | uint64_t m_nFoundLostPktNum; 243 | uint64_t m_nTotalSendTimes; 244 | 245 | uint32_t m_nAckTakeTime = 0; 246 | uint32_t m_nTickTakeTime = 0; 247 | 248 | uint32_t m_nTheirTimestampDiff = 0; 249 | uint32_t m_nMyTimestampDiff = 0; 250 | 251 | bool m_bWaitWrite, m_bWaitRead, m_bWaitConnect; 252 | bool m_bEnableFec; 253 | bool m_bFastAck; 254 | bool m_bDelayAck; 255 | 256 | std::shared_ptr m_ptrCongestionController; 257 | std::shared_ptr m_ptrRoundTripMeter; 258 | std::shared_ptr m_ptrPacketLostCounter; 259 | std::shared_ptr m_ptrClocker; 260 | 261 | 262 | std::deque> m_deqNotAckedCmdPacket;//used for sync and close cmd 263 | std::deque> m_deqNotAckedDataPacket; 264 | 265 | 266 | //std::deque> m_deqSendTimeOrderedDataPacket;//send order 267 | 268 | std::map, std::shared_ptr> m_mapReceivedPacket; 269 | 270 | std::deque> m_deqReady4ReadPacket; 271 | 272 | DelaySampleHistroy m_MyDelayHistory; 273 | DelaySampleHistroy m_RemoteDelayHistory; 274 | 275 | }; 276 | 277 | } 278 | 279 | --------------------------------------------------------------------------------