diff --git a/thirdparty/README.md b/thirdparty/README.md index df899c120a..6d0e54f7e1 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -223,7 +223,7 @@ ## yasio - Upstream: https://github.com/yasio/yasio -- Version: git 3.37.5-4e8b63a(2641) +- Version: 3.37.6 - License: MIT WITH Anti-996 ## zlib diff --git a/thirdparty/yasio/cxx17/shared_mutex.hpp b/thirdparty/yasio/cxx17/shared_mutex.hpp index 1cc80de59c..f32c458c6a 100644 --- a/thirdparty/yasio/cxx17/shared_mutex.hpp +++ b/thirdparty/yasio/cxx17/shared_mutex.hpp @@ -35,92 +35,126 @@ SOFTWARE. # include #else # include -# if defined(_WIN32) -# if !defined(WIN32_LEAN_AND_MEAN) -# define WIN32_LEAN_AND_MEAN -# endif -# include -# define yasio__smtx_t SRWLOCK -# define yasio__smtx_init(rwlock, attr) InitializeSRWLock(rwlock) -# define yasio__smtx_destroy(rwlock) -# define yasio__smtx_lock_shared(rwlock) AcquireSRWLockShared(rwlock) -# define yasio__smtx_trylock_shared(rwlock) !!TryAcquireSRWLockShared(rwlock) -# define yasio__smtx_lock_exclusive(rwlock) AcquireSRWLockExclusive(rwlock) -# define yasio__smtx_trylock_exclusive(rwlock) !!TryAcquireSRWLockExclusive(rwlock) -# define yasio__smtx_unlock_shared(rwlock) ReleaseSRWLockShared(rwlock) -# define yasio__smtx_unlock_exclusive(rwlock) ReleaseSRWLockExclusive(rwlock) -# else -# include -# define yasio__smtx_t pthread_rwlock_t -# define yasio__smtx_init(rwlock, attr) pthread_rwlock_init(rwlock, attr) -# define yasio__smtx_destroy(rwlock) pthread_rwlock_destroy(rwlock) -# define yasio__smtx_lock_shared(rwlock) pthread_rwlock_rdlock(rwlock) -# define yasio__smtx_trylock_shared(rwlock) pthread_rwlock_tryrdlock(rwlock) != 0 -# define yasio__smtx_lock_exclusive(rwlock) pthread_rwlock_wrlock(rwlock) -# define yasio__smtx_trylock_exclusive(rwlock) pthread_rwlock_trywrlock(rwlock) != 0 -# define yasio__smtx_unlock_shared(rwlock) pthread_rwlock_unlock(rwlock) -# define yasio__smtx_unlock_exclusive(rwlock) pthread_rwlock_unlock(rwlock) -# endif -# define yaso__throw_error(e) YASIO__THROW0(std::system_error(std::make_error_code(e), "")) # include - -// CLASS TEMPLATE shared_lock +# include +# define yaso__throw_error(e) YASIO__THROW0(std::system_error(std::make_error_code(e), "")) namespace cxx17 { +// CLASS TEMPLATE shared_mutex, copy from: https://github.com/boostorg/thread/blob/develop/include/boost/thread/v2/shared_mutex.hpp class shared_mutex { -public: - typedef yasio__smtx_t* native_handle_type; + typedef std::mutex mutex_t; + typedef std::condition_variable cond_t; + typedef unsigned count_t; - shared_mutex() // strengthened + mutex_t mut_; + cond_t gate1_; + // the gate2_ condition variable is only used by functions that + // have taken write_entered_ but are waiting for no_readers() + cond_t gate2_; + count_t state_; + + static const count_t write_entered_ = 1U << (sizeof(count_t) * CHAR_BIT - 1); + static const count_t n_readers_ = ~write_entered_; + + bool no_writer() const { return (state_ & write_entered_) == 0; } + + bool one_writer() const { return (state_ & write_entered_) != 0; } + + bool no_writer_no_readers() const { - yasio__smtx_init(&this->_Myhandle, nullptr); + // return (state_ & write_entered_) == 0 && + // (state_ & n_readers_) == 0; + return state_ == 0; } - ~shared_mutex() { yasio__smtx_destroy(&this->_Myhandle); } + bool no_writer_no_max_readers() const { return (state_ & write_entered_) == 0 && (state_ & n_readers_) != n_readers_; } - void lock() /* strengthened */ - { // lock exclusive - yasio__smtx_lock_exclusive(&this->_Myhandle); + bool no_readers() const { return (state_ & n_readers_) == 0; } + + bool one_or_more_readers() const { return (state_ & n_readers_) > 0; } + + shared_mutex(shared_mutex const&) = delete; + shared_mutex& operator=(shared_mutex const&) = delete; + +public: + shared_mutex() : state_(0) {} + ~shared_mutex() { std::lock_guard _(mut_); } + + // Exclusive ownership + + void lock() + { + std::unique_lock lk(mut_); + gate1_.wait(lk, std::bind(&shared_mutex::no_writer, std::ref(*this))); + state_ |= write_entered_; + gate2_.wait(lk, std::bind(&shared_mutex::no_readers, std::ref(*this))); + } + bool try_lock() + { + std::unique_lock lk(mut_); + if (!no_writer_no_readers()) + { + return false; + } + state_ = write_entered_; + return true; + } + void unlock() + { + std::lock_guard _(mut_); + assert(one_writer()); + assert(no_readers()); + state_ = 0; + // notify all since multiple *lock_shared*() calls may be able + // to proceed in response to this notification + gate1_.notify_all(); } - bool try_lock() /* strengthened */ - { // try to lock exclusive - return yasio__smtx_trylock_exclusive(&this->_Myhandle); + // Shared ownership + + void lock_shared() + { + std::unique_lock lk(mut_); + gate1_.wait(lk, std::bind(&shared_mutex::no_writer_no_max_readers, std::ref(*this))); + count_t num_readers = (state_ & n_readers_) + 1; + state_ &= ~n_readers_; + state_ |= num_readers; } - - void unlock() /* strengthened */ - { // unlock exclusive - yasio__smtx_unlock_exclusive(&this->_Myhandle); + bool try_lock_shared() + { + std::unique_lock lk(mut_); + if (!no_writer_no_max_readers()) + { + return false; + } + count_t num_readers = (state_ & n_readers_) + 1; + state_ &= ~n_readers_; + state_ |= num_readers; + return true; } - - void lock_shared() /* strengthened */ - { // lock non-exclusive - yasio__smtx_lock_shared(&this->_Myhandle); + void unlock_shared() + { + std::lock_guard _(mut_); + assert(one_or_more_readers()); + count_t num_readers = (state_ & n_readers_) - 1; + state_ &= ~n_readers_; + state_ |= num_readers; + if (no_writer()) + { + if (num_readers == n_readers_ - 1) + gate1_.notify_one(); + } + else + { + if (num_readers == 0) + gate2_.notify_one(); + } } - - bool try_lock_shared() /* strengthened */ - { // try to lock non-exclusive - return yasio__smtx_trylock_shared(&this->_Myhandle); - } - - void unlock_shared() /* strengthened */ - { // unlock non-exclusive - yasio__smtx_unlock_shared(&this->_Myhandle); - } - - native_handle_type native_handle() /* strengthened */ - { // get native handle - return &_Myhandle; - } - - shared_mutex(const shared_mutex&) = delete; - shared_mutex& operator=(const shared_mutex&) = delete; - -private: - yasio__smtx_t _Myhandle; // the lock object }; + // CLASS TEMPLATE shared_lock -template class shared_lock { // shareable lock +template +class shared_lock { public: using mutex_type = _Mutex; diff --git a/thirdparty/yasio/cxx17/string_view.hpp b/thirdparty/yasio/cxx17/string_view.hpp index 5102650947..50c59a6d7e 100644 --- a/thirdparty/yasio/cxx17/string_view.hpp +++ b/thirdparty/yasio/cxx17/string_view.hpp @@ -36,7 +36,7 @@ See: https://github.com/bitwizeshift/string_view-standalone #include "yasio/compiler/feature_test.hpp" /// wcsncasecmp workaround for android API level < 23, copy from msvc ucrt 10.0.18362.0 'wcsnicmp' -#if defined(__ANDROID_API__) && __ANDROID_API__ < 23 +#if (defined(__ANDROID_API__) && __ANDROID_API__ < 23) || defined(__MINGW32__) inline int wcsncasecmp(wchar_t const* const lhs, wchar_t const* const rhs, size_t const count) { if (count == 0) diff --git a/thirdparty/yasio/detail/config.hpp b/thirdparty/yasio/detail/config.hpp index f93658a3d9..a9732e4550 100644 --- a/thirdparty/yasio/detail/config.hpp +++ b/thirdparty/yasio/detail/config.hpp @@ -186,7 +186,7 @@ SOFTWARE. /* ** The yasio version macros */ -#define YASIO_VERSION_NUM 0x033705 +#define YASIO_VERSION_NUM 0x033706 /* ** The macros used by io_service. @@ -220,6 +220,6 @@ SOFTWARE. // https://c-ares.haxx.se/changelog.html // https://github.com/c-ares/c-ares/issues/276 // https://github.com/c-ares/c-ares/pull/148 -#define YASIO_CARES_FALLBACK_DNS "8.8.8.8,223.5.5.5,114.114.114.114" +#define YASIO_FALLBACK_NAME_SERVERS "8.8.8.8,223.5.5.5,114.114.114.114" #endif diff --git a/thirdparty/yasio/detail/socket.hpp b/thirdparty/yasio/detail/socket.hpp index 66b7b07778..6c02974ff3 100644 --- a/thirdparty/yasio/detail/socket.hpp +++ b/thirdparty/yasio/detail/socket.hpp @@ -29,13 +29,23 @@ SOFTWARE. #ifndef YASIO__SOCKET_HPP #define YASIO__SOCKET_HPP +#include "yasio/detail/config.hpp" + #ifdef _WIN32 # if !defined(WIN32_LEAN_AND_MEAN) # define WIN32_LEAN_AND_MEAN # endif # include # include -# if defined(_WIN32) && !defined(_WINSTORE) +# if defined(YASIO_INSIDE_UNREAL) +# if !defined(TRUE) +# define TRUE 1 +# endif +# if !defined(FALSE) +# define FALSE 0 +# endif +# endif +# if !defined(_WINSTORE) # include # include # endif @@ -185,7 +195,17 @@ typedef int socket_native_type; #define IN_MAX_ADDRSTRLEN INET6_ADDRSTRLEN -#if !defined(_WS2IPDEF_) +// Workaround for older MinGW missing AI_XXX macros +#if defined(__MINGW32__) +# if !defined(AI_ALL) +# define AI_ALL 0x00000100 +# endif +# if !defined(AI_V4MAPPED) +# define AI_V4MAPPED 0x00000800 +# endif +#endif + +#if !defined(_WS2IPDEF_) || defined(__MINGW32__) inline bool IN4_IS_ADDR_LOOPBACK(const in_addr* a) { return ((a->s_addr & 0xff) == 0x7f); // 127/8 diff --git a/thirdparty/yasio/xxsocket.cpp b/thirdparty/yasio/xxsocket.cpp index 9040fd2658..b63030c6b7 100644 --- a/thirdparty/yasio/xxsocket.cpp +++ b/thirdparty/yasio/xxsocket.cpp @@ -460,8 +460,8 @@ bool xxsocket::open_ex(int af, int type, int protocol) bool xxsocket::accept_ex(SOCKET sockfd_listened, SOCKET sockfd_prepared, PVOID lpOutputBuffer, DWORD dwReceiveDataLength, DWORD dwLocalAddressLength, DWORD dwRemoteAddressLength, LPDWORD lpdwBytesReceived, LPOVERLAPPED lpOverlapped) { - return __accept_ex(sockfd_listened, sockfd_prepared, lpOutputBuffer, dwReceiveDataLength, dwLocalAddressLength, dwRemoteAddressLength, lpdwBytesReceived, - lpOverlapped) != FALSE; + return !!__accept_ex(sockfd_listened, sockfd_prepared, lpOutputBuffer, dwReceiveDataLength, dwLocalAddressLength, dwRemoteAddressLength, lpdwBytesReceived, + lpOverlapped); } bool xxsocket::connect_ex(SOCKET s, const struct sockaddr* name, int namelen, PVOID lpSendBuffer, DWORD dwSendDataLength, LPDWORD lpdwBytesSent, diff --git a/thirdparty/yasio/xxsocket.hpp b/thirdparty/yasio/xxsocket.hpp index d4464a9003..32bd43a969 100644 --- a/thirdparty/yasio/xxsocket.hpp +++ b/thirdparty/yasio/xxsocket.hpp @@ -38,9 +38,8 @@ SOFTWARE. #include #include #include -#include "yasio/detail/config.hpp" -#include "yasio/detail/logging.hpp" #include "yasio/detail/socket.hpp" +#include "yasio/detail/logging.hpp" #if defined(_MSC_VER) # pragma warning(push) diff --git a/thirdparty/yasio/yasio.cpp b/thirdparty/yasio/yasio.cpp index 94b4c8e1ee..af873cebd8 100644 --- a/thirdparty/yasio/yasio.cpp +++ b/thirdparty/yasio/yasio.cpp @@ -1334,13 +1334,14 @@ void io_service::init_ssl_context() else SSL_CTX_set_verify(ssl_ctx_, SSL_VERIFY_NONE, nullptr); # elif YASIO_SSL_BACKEND == 2 - const char* pers = "yasio_ssl_client"; ssl_ctx_ = new SSL_CTX(); ::mbedtls_ssl_config_init(&ssl_ctx_->conf); ::mbedtls_x509_crt_init(&ssl_ctx_->cacert); ::mbedtls_ctr_drbg_init(&ssl_ctx_->ctr_drbg); ::mbedtls_entropy_init(&ssl_ctx_->entropy); - int ret = ::mbedtls_ctr_drbg_seed(&ssl_ctx_->ctr_drbg, ::mbedtls_entropy_func, &ssl_ctx_->entropy, (const unsigned char*)pers, strlen(pers)); + using namespace cxx17; + auto pers = "yasio_ssl_client"_sv; + int ret = ::mbedtls_ctr_drbg_seed(&ssl_ctx_->ctr_drbg, ::mbedtls_entropy_func, &ssl_ctx_->entropy, (const unsigned char*)pers.data(), pers.length()); if (ret != 0) YASIO_KLOGE("mbedtls_ctr_drbg_seed fail with ret=%d", ret); @@ -1535,21 +1536,27 @@ void io_service::config_ares_name_servers() std::string nscsv; // list all dns servers for resov problem diagnosis ares_addr_node* name_servers = nullptr; - int status = ::ares_get_servers(ares_, &name_servers); + const char* what = "system"; + if (!options_.name_servers_.empty()) + { + ::ares_set_servers_csv(ares_, options_.name_servers_.c_str()); + what = "custom"; + } + int status = ::ares_get_servers(ares_, &name_servers); if (status == ARES_SUCCESS) { for (auto name_server = name_servers; name_server != nullptr; name_server = name_server->next) endpoint::inaddr_to_csv_nl(name_server->family, &name_server->addr, nscsv); if (!nscsv.empty()) // if no valid name server, use predefined fallback dns - YASIO_KLOGD("[c-ares] use system dns: %s", nscsv.c_str()); + YASIO_KLOGI("[c-ares] use %s dns: %s", what, nscsv.c_str()); else { - status = ::ares_set_servers_csv(ares_, YASIO_CARES_FALLBACK_DNS); + status = ::ares_set_servers_csv(ares_, YASIO_FALLBACK_NAME_SERVERS); if (status == 0) - YASIO_KLOGW("[c-ares] set fallback dns: '%s' succeed", YASIO_CARES_FALLBACK_DNS); + YASIO_KLOGW("[c-ares] set fallback dns: '%s' succeed", YASIO_FALLBACK_NAME_SERVERS); else - YASIO_KLOGE("[c-ares] set fallback dns: '%s' failed, detail: %s", YASIO_CARES_FALLBACK_DNS, ::ares_strerror(status)); + YASIO_KLOGE("[c-ares] set fallback dns: '%s' failed, detail: %s", YASIO_FALLBACK_NAME_SERVERS, ::ares_strerror(status)); } ::ares_free_data(name_servers); } @@ -2267,6 +2274,12 @@ void io_service::set_option_internal(int opt, va_list ap) // lgtm [cpp/poorly-do case YOPT_S_DNS_DIRTY: options_.dns_dirty_ = true; break; +#if defined(YASIO_HAVE_CARES) + case YOPT_S_DNS_LIST: + options_.name_servers_ = va_arg(ap, const char*); + options_.dns_dirty_ = true; + break; +#endif case YOPT_C_UNPACK_PARAMS: { auto channel = channel_at(static_cast(va_arg(ap, int))); if (channel) diff --git a/thirdparty/yasio/yasio.hpp b/thirdparty/yasio/yasio.hpp index 82160fc887..0a3961cf02 100644 --- a/thirdparty/yasio/yasio.hpp +++ b/thirdparty/yasio/yasio.hpp @@ -167,6 +167,10 @@ enum // remarks: you should set this option after your device network changed YOPT_S_DNS_DIRTY, + // Set custom dns servers + // params: servers: const char*("xxx.xxx.xxx[:port],xxx.xxx.xxx.xxx[:port]") + YOPT_S_DNS_LIST, + // Sets channel length field based frame decode function, native C++ ONLY // params: index:int, func:decode_len_fn_t* YOPT_C_LFBFD_FN = 101, @@ -853,9 +857,14 @@ public: #if !defined(YASIO_MINIFY_EVENT) /* Gets to transport user data when process this event */ - template _Uty transport_ud() const { return (_Uty)(uintptr_t)source_ud_; } + template + _Uty transport_ud() const + { + return (_Uty)(uintptr_t)source_ud_; + } /* Sets trasnport user data when process this event */ - template void transport_ud(_Uty uval) + template + void transport_ud(_Uty uval) { source_ud_ = (void*)(uintptr_t)uval; @@ -1183,6 +1192,10 @@ private: // The full path cacert(.pem) file for ssl verifaction std::string cafile_; #endif + +#if defined(YASIO_HAVE_CARES) + std::string name_servers_; +#endif } options_; // The ip stack version supported by localhost