From 78714eceea1d53589ec23a30082ed5c77237e8d0 Mon Sep 17 00:00:00 2001 From: Venkata Sharath Chandra Manchala Date: Tue, 2 Mar 2021 11:04:31 -0800 Subject: [PATCH 1/4] Implement createchannelasyn for requesting channels using retry logic --- dev/PushNotifications/ChannelResult.cpp | 13 +-- dev/PushNotifications/ChannelResult.h | 7 +- dev/PushNotifications/PushManager.cpp | 102 +++++++++++++++++++++++- dev/PushNotifications/PushManager.h | 9 +++ 4 files changed, 124 insertions(+), 7 deletions(-) diff --git a/dev/PushNotifications/ChannelResult.cpp b/dev/PushNotifications/ChannelResult.cpp index e29ab17ff9..1703c72cc5 100644 --- a/dev/PushNotifications/ChannelResult.cpp +++ b/dev/PushNotifications/ChannelResult.cpp @@ -4,23 +4,26 @@ #include "pch.h" #include "ChannelResult.h" #include "ChannelResult.g.cpp" +#include namespace winrt::Microsoft::ProjectReunion::implementation { - ChannelResult::ChannelResult(Windows::Networking::PushNotifications::PushNotificationChannel const& channel, winrt::hresult const& extendedError, Microsoft::ProjectReunion::ChannelStatus const& status) + ChannelResult::ChannelResult(winrt::Windows::Networking::PushNotifications::PushNotificationChannel const channel, winrt::hresult const extendedError, Microsoft::ProjectReunion::ChannelStatus const status) { - throw hresult_not_implemented(); + m_channel = channel; + m_extendedError = extendedError; + m_channelStatus = status; } Windows::Networking::PushNotifications::PushNotificationChannel ChannelResult::Channel() { - throw hresult_not_implemented(); + return m_channel; } winrt::hresult ChannelResult::ExtendedError() { - throw hresult_not_implemented(); + return m_extendedError; } Microsoft::ProjectReunion::ChannelStatus ChannelResult::Status() { - throw hresult_not_implemented(); + return m_channelStatus; } } diff --git a/dev/PushNotifications/ChannelResult.h b/dev/PushNotifications/ChannelResult.h index 0e3da62d49..b59083609f 100644 --- a/dev/PushNotifications/ChannelResult.h +++ b/dev/PushNotifications/ChannelResult.h @@ -10,10 +10,15 @@ namespace winrt::Microsoft::ProjectReunion::implementation { ChannelResult() = default; - ChannelResult(Windows::Networking::PushNotifications::PushNotificationChannel const& channel, winrt::hresult const& extendedError, Microsoft::ProjectReunion::ChannelStatus const& status); + ChannelResult(Windows::Networking::PushNotifications::PushNotificationChannel const channel, winrt::hresult const extendedError, Microsoft::ProjectReunion::ChannelStatus const status); Windows::Networking::PushNotifications::PushNotificationChannel Channel(); winrt::hresult ExtendedError(); Microsoft::ProjectReunion::ChannelStatus Status(); + + private: + Windows::Networking::PushNotifications::PushNotificationChannel m_channel{ nullptr }; + winrt::hresult m_extendedError; + Microsoft::ProjectReunion::ChannelStatus m_channelStatus; }; } namespace winrt::Microsoft::ProjectReunion::factory_implementation diff --git a/dev/PushNotifications/PushManager.cpp b/dev/PushNotifications/PushManager.cpp index 52f9d657d9..31a9370c42 100644 --- a/dev/PushNotifications/PushManager.cpp +++ b/dev/PushNotifications/PushManager.cpp @@ -4,11 +4,111 @@ #include "pch.h" #include "PushManager.h" #include "PushManager.g.cpp" +#include +#include +#include +#include +#include +#include +#include + +using namespace winrt::Windows::Networking::PushNotifications; +using namespace winrt; + +// MAX BACKOFF TIME IS 16MINUTES +#define MAX_BACKOFF_SECONDS 960 + +// Error code - platform is not connected +#define WNP_E_NOT_CONNECTED 0x880403E8L + +// Error code - platform reconnecting with wns +#define WNP_E_RECONNECTING 0x880403E9L + +// Error code - Current bind operation failed because another bind operation in progress +#define WNP_E_BIND_USER_BUSY 0x880403FEL namespace winrt::Microsoft::ProjectReunion::implementation { + std::list PushManager::remoteIdList; + std::mutex PushManager::mtx; + std::unique_lock PushManager::lock (mtx, std::defer_lock); // Avoid locking during the constructor call + + bool PushManager::isChannelRequestRetryable(const winrt::hresult& hrException) + { + switch (hrException) + { + case HRESULT_FROM_WIN32(ERROR_TIMEOUT): + // E_TIMEOUT + case WNP_E_NOT_CONNECTED: + case WPN_E_OUTSTANDING_CHANNEL_REQUEST: + case WNP_E_RECONNECTING + case WNP_E_BIND_USER_BUSY: + return true; + default: + return false; + } + } + Windows::Foundation::IAsyncOperationWithProgress PushManager::CreateChannelAsync(winrt::guid remoteId) { - throw hresult_not_implemented(); + winrt::Microsoft::ProjectReunion::ChannelResult channelResult{ nullptr }; + auto progress{ co_await winrt::get_progress_token() }; + + GUID remoteIdAbiGuid = reinterpret_cast(remoteId); + if (remoteIdAbiGuid == GUID_NULL) + { + channelResult = winrt::make(nullptr, E_INVALIDARG, ChannelStatus::CompletedFailure); + co_return channelResult; + } + + lock.lock(); + if (std::find(remoteIdList.begin(), remoteIdList.end(), remoteId) != remoteIdList.end()) + { + progress(winrt::make(nullptr, WPN_E_OUTSTANDING_CHANNEL_REQUEST, ChannelStatus::InProgress)); + channelResult = winrt::make(nullptr, WPN_E_OUTSTANDING_CHANNEL_REQUEST, ChannelStatus::CompletedFailure); + co_return channelResult; + } + else + { + remoteIdList.push_back(remoteId); + } + lock.unlock(); + + PushNotificationChannelManager channelManager{}; + + for (auto backOffTimeInSeconds = 30; backOffTimeInSeconds <= MAX_BACKOFF_SECONDS * 2; backOffTimeInSeconds *= 2) + { + try + { + auto pushChannel = co_await channelManager.CreatePushNotificationChannelForApplicationAsync(); + + if (pushChannel != nullptr) + { + channelResult = winrt::make(pushChannel, S_OK, ChannelStatus::CompletedSuccess); + break; + } + } + catch (winrt::hresult_error const& ex) + { + if ((backOffTimeInSeconds <= MAX_BACKOFF_SECONDS) && isChannelRequestRetryable(ex.code())) + { + progress(winrt::make(nullptr, ex.code(), ChannelStatus::InProgressRetry)); + } + else + { + channelResult = winrt::make(nullptr, ex.code(), ChannelStatus::CompletedFailure); + break; + } + } + + co_await winrt::resume_after(std::chrono::seconds(backOffTimeInSeconds)); + } + + lock.lock(); + remoteIdList.remove(remoteId); + lock.unlock(); + + co_return channelResult; + } } diff --git a/dev/PushNotifications/PushManager.h b/dev/PushNotifications/PushManager.h index 63398ef8a1..4d0b3bad92 100644 --- a/dev/PushNotifications/PushManager.h +++ b/dev/PushNotifications/PushManager.h @@ -2,7 +2,10 @@ // Licensed under the MIT License. See LICENSE in the project root for license information. #pragma once + #include "PushManager.g.h" +#include +#include namespace winrt::Microsoft::ProjectReunion::implementation { @@ -11,6 +14,12 @@ namespace winrt::Microsoft::ProjectReunion::implementation PushManager() = default; static Windows::Foundation::IAsyncOperationWithProgress CreateChannelAsync(winrt::guid remoteId); + + private: + static bool isChannelRequestRetryable(const winrt::hresult& hrException); + static std::list remoteIdList; + static std::mutex mtx; + static std::unique_lock lock; }; } namespace winrt::Microsoft::ProjectReunion::factory_implementation From 1a35ff26b8274a0f9105b919774a2f52041c41be Mon Sep 17 00:00:00 2001 From: Venkata Sharath Chandra Manchala Date: Fri, 5 Mar 2021 10:34:48 -0800 Subject: [PATCH 2/4] Address comments and also introduce PushNotificationErrorcodes.h --- dev/PushNotifications/ChannelResult.h | 2 +- dev/PushNotifications/PushManager.cpp | 124 ++++++++---------- dev/PushNotifications/PushManager.h | 8 +- .../PushNotificationErrorCodes.h | 14 ++ .../PushNotifications.vcxitems | 1 + 5 files changed, 75 insertions(+), 74 deletions(-) create mode 100644 dev/PushNotifications/PushNotificationErrorCodes.h diff --git a/dev/PushNotifications/ChannelResult.h b/dev/PushNotifications/ChannelResult.h index b59083609f..551827ad65 100644 --- a/dev/PushNotifications/ChannelResult.h +++ b/dev/PushNotifications/ChannelResult.h @@ -18,7 +18,7 @@ namespace winrt::Microsoft::ProjectReunion::implementation private: Windows::Networking::PushNotifications::PushNotificationChannel m_channel{ nullptr }; winrt::hresult m_extendedError; - Microsoft::ProjectReunion::ChannelStatus m_channelStatus; + ChannelStatus m_channelStatus{}; }; } namespace winrt::Microsoft::ProjectReunion::factory_implementation diff --git a/dev/PushNotifications/PushManager.cpp b/dev/PushNotifications/PushManager.cpp index 31a9370c42..a583f0d651 100644 --- a/dev/PushNotifications/PushManager.cpp +++ b/dev/PushNotifications/PushManager.cpp @@ -7,42 +7,31 @@ #include #include #include -#include +#include #include #include #include +#include using namespace winrt::Windows::Networking::PushNotifications; -using namespace winrt; - -// MAX BACKOFF TIME IS 16MINUTES -#define MAX_BACKOFF_SECONDS 960 - -// Error code - platform is not connected -#define WNP_E_NOT_CONNECTED 0x880403E8L - -// Error code - platform reconnecting with wns -#define WNP_E_RECONNECTING 0x880403E9L - -// Error code - Current bind operation failed because another bind operation in progress -#define WNP_E_BIND_USER_BUSY 0x880403FEL namespace winrt::Microsoft::ProjectReunion::implementation { - std::list PushManager::remoteIdList; - std::mutex PushManager::mtx; - std::unique_lock PushManager::lock (mtx, std::defer_lock); // Avoid locking during the constructor call + std::vector PushManager::s_remoteIdList; + std::mutex PushManager::s_mutex; + std::unique_lock PushManager::s_lock (s_mutex, std::defer_lock); // Avoid locking during the constructor call + inline constexpr std::uint32_t c_maxBackoffSeconds{ 960 }; bool PushManager::isChannelRequestRetryable(const winrt::hresult& hrException) { switch (hrException) { case HRESULT_FROM_WIN32(ERROR_TIMEOUT): - // E_TIMEOUT - case WNP_E_NOT_CONNECTED: + case WnpErrors::WNP_E_NOT_CONNECTED: case WPN_E_OUTSTANDING_CHANNEL_REQUEST: - case WNP_E_RECONNECTING - case WNP_E_BIND_USER_BUSY: + case WnpErrors:: WNP_E_RECONNECTING: + case WnpErrors::WNP_E_BIND_USER_BUSY: + case RPC_S_SERVER_UNAVAILABLE: return true; default: return false; @@ -54,61 +43,58 @@ namespace winrt::Microsoft::ProjectReunion::implementation winrt::Microsoft::ProjectReunion::ChannelResult channelResult{ nullptr }; auto progress{ co_await winrt::get_progress_token() }; - GUID remoteIdAbiGuid = reinterpret_cast(remoteId); - if (remoteIdAbiGuid == GUID_NULL) + winrt::check_pointer(&remoteId); + + s_lock.lock(); + if (std::find(s_remoteIdList.begin(), s_remoteIdList.end(), remoteId) != s_remoteIdList.end()) { - channelResult = winrt::make(nullptr, E_INVALIDARG, ChannelStatus::CompletedFailure); + progress(winrt::make(nullptr, WPN_E_OUTSTANDING_CHANNEL_REQUEST, ChannelStatus::InProgress)); + channelResult = winrt::make(nullptr, WPN_E_OUTSTANDING_CHANNEL_REQUEST, ChannelStatus::CompletedFailure); co_return channelResult; } + else + { + s_remoteIdList.push_back(remoteId); + } + s_lock.unlock(); - lock.lock(); - if (std::find(remoteIdList.begin(), remoteIdList.end(), remoteId) != remoteIdList.end()) - { - progress(winrt::make(nullptr, WPN_E_OUTSTANDING_CHANNEL_REQUEST, ChannelStatus::InProgress)); - channelResult = winrt::make(nullptr, WPN_E_OUTSTANDING_CHANNEL_REQUEST, ChannelStatus::CompletedFailure); - co_return channelResult; - } - else - { - remoteIdList.push_back(remoteId); - } - lock.unlock(); - - PushNotificationChannelManager channelManager{}; - - for (auto backOffTimeInSeconds = 30; backOffTimeInSeconds <= MAX_BACKOFF_SECONDS * 2; backOffTimeInSeconds *= 2) - { - try - { - auto pushChannel = co_await channelManager.CreatePushNotificationChannelForApplicationAsync(); - - if (pushChannel != nullptr) - { - channelResult = winrt::make(pushChannel, S_OK, ChannelStatus::CompletedSuccess); - break; - } - } - catch (winrt::hresult_error const& ex) - { - if ((backOffTimeInSeconds <= MAX_BACKOFF_SECONDS) && isChannelRequestRetryable(ex.code())) - { - progress(winrt::make(nullptr, ex.code(), ChannelStatus::InProgressRetry)); - } - else - { - channelResult = winrt::make(nullptr, ex.code(), ChannelStatus::CompletedFailure); - break; - } - } + PushNotificationChannelManager channelManager{}; - co_await winrt::resume_after(std::chrono::seconds(backOffTimeInSeconds)); - } + for (auto backOffTimeInSeconds = 30; backOffTimeInSeconds <= c_maxBackoffSeconds * 2; backOffTimeInSeconds *= 2) + { + try + { + auto pushChannel = co_await channelManager.CreatePushNotificationChannelForApplicationAsync(); + + if (pushChannel != nullptr) + { + channelResult = winrt::make(pushChannel, S_OK, ChannelStatus::CompletedSuccess); + break; + } + } + catch (...) + { + auto ex = hresult_error(to_hresult(), take_ownership_from_abi); + + if ((backOffTimeInSeconds <= c_maxBackoffSeconds) && isChannelRequestRetryable(ex.code())) + { + progress(winrt::make(nullptr, ex.code(), ChannelStatus::InProgressRetry)); + } + else + { + channelResult = winrt::make(nullptr, ex.code(), ChannelStatus::CompletedFailure); + break; + } + } + + co_await winrt::resume_after(std::chrono::seconds(backOffTimeInSeconds)); + } - lock.lock(); - remoteIdList.remove(remoteId); - lock.unlock(); + s_lock.lock(); + std::remove(s_remoteIdList.begin(), s_remoteIdList.end(), remoteId); + s_lock.unlock(); - co_return channelResult; + co_return channelResult; } } diff --git a/dev/PushNotifications/PushManager.h b/dev/PushNotifications/PushManager.h index 4d0b3bad92..83eb7ac722 100644 --- a/dev/PushNotifications/PushManager.h +++ b/dev/PushNotifications/PushManager.h @@ -4,7 +4,7 @@ #pragma once #include "PushManager.g.h" -#include +#include #include namespace winrt::Microsoft::ProjectReunion::implementation @@ -17,9 +17,9 @@ namespace winrt::Microsoft::ProjectReunion::implementation private: static bool isChannelRequestRetryable(const winrt::hresult& hrException); - static std::list remoteIdList; - static std::mutex mtx; - static std::unique_lock lock; + static std::vector s_remoteIdList; + static std::mutex s_mutex; + static std::unique_lock s_lock; }; } namespace winrt::Microsoft::ProjectReunion::factory_implementation diff --git a/dev/PushNotifications/PushNotificationErrorCodes.h b/dev/PushNotifications/PushNotificationErrorCodes.h new file mode 100644 index 0000000000..6522608947 --- /dev/null +++ b/dev/PushNotifications/PushNotificationErrorCodes.h @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +#pragma once + +namespace winrt::Microsoft::ProjectReunion::implementation +{ + enum WnpErrors + { + WNP_E_NOT_CONNECTED = 0x880403E8L, + WNP_E_RECONNECTING = 0x880403E9L, + WNP_E_BIND_USER_BUSY = 0x880403FEL, + }; +} diff --git a/dev/PushNotifications/PushNotifications.vcxitems b/dev/PushNotifications/PushNotifications.vcxitems index 277e473f00..c1fc2a8c31 100644 --- a/dev/PushNotifications/PushNotifications.vcxitems +++ b/dev/PushNotifications/PushNotifications.vcxitems @@ -24,5 +24,6 @@ + \ No newline at end of file From 3c6e8bcfa0c2ad82b671b44ea03d05467168eda9 Mon Sep 17 00:00:00 2001 From: Venkata Sharath Chandra Manchala Date: Sun, 7 Mar 2021 19:22:51 -0800 Subject: [PATCH 3/4] Lock only the remoteIdList --- dev/PushNotifications/PushManager.cpp | 38 +++++++++++++++---- .../PushNotificationErrorCodes.h | 14 ------- .../PushNotifications.vcxitems | 1 - 3 files changed, 30 insertions(+), 23 deletions(-) delete mode 100644 dev/PushNotifications/PushNotificationErrorCodes.h diff --git a/dev/PushNotifications/PushManager.cpp b/dev/PushNotifications/PushManager.cpp index a583f0d651..f23dbf7094 100644 --- a/dev/PushNotifications/PushManager.cpp +++ b/dev/PushNotifications/PushManager.cpp @@ -11,7 +11,6 @@ #include #include #include -#include using namespace winrt::Windows::Networking::PushNotifications; @@ -22,15 +21,19 @@ namespace winrt::Microsoft::ProjectReunion::implementation std::unique_lock PushManager::s_lock (s_mutex, std::defer_lock); // Avoid locking during the constructor call inline constexpr std::uint32_t c_maxBackoffSeconds{ 960 }; - bool PushManager::isChannelRequestRetryable(const winrt::hresult& hrException) + const HRESULT WNP_E_NOT_CONNECTED = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x880403E8L); + const HRESULT WNP_E_RECONNECTING = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x880403E9L); + const HRESULT WNP_E_BIND_USER_BUSY = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x880403FEL); + + bool PushManager::isChannelRequestRetryable(const winrt::hresult& hr) { - switch (hrException) + switch (hr) { case HRESULT_FROM_WIN32(ERROR_TIMEOUT): - case WnpErrors::WNP_E_NOT_CONNECTED: + case WNP_E_NOT_CONNECTED: case WPN_E_OUTSTANDING_CHANNEL_REQUEST: - case WnpErrors:: WNP_E_RECONNECTING: - case WnpErrors::WNP_E_BIND_USER_BUSY: + case WNP_E_RECONNECTING: + case WNP_E_BIND_USER_BUSY: case RPC_S_SERVER_UNAVAILABLE: return true; default: @@ -38,6 +41,18 @@ namespace winrt::Microsoft::ProjectReunion::implementation } } + bool IsPackagedProcess() + { + uint32_t packageFullNameLength = 0; + const auto rc{ GetCurrentPackageFullName(&packageFullNameLength, nullptr) }; + + if (rc != ERROR_INSUFFICIENT_BUFFER) + { + winrt::throw_hresult(rc); + } + return rc == ERROR_INSUFFICIENT_BUFFER; + } + Windows::Foundation::IAsyncOperationWithProgress PushManager::CreateChannelAsync(winrt::guid remoteId) { winrt::Microsoft::ProjectReunion::ChannelResult channelResult{ nullptr }; @@ -48,23 +63,30 @@ namespace winrt::Microsoft::ProjectReunion::implementation s_lock.lock(); if (std::find(s_remoteIdList.begin(), s_remoteIdList.end(), remoteId) != s_remoteIdList.end()) { + s_lock.unlock(); progress(winrt::make(nullptr, WPN_E_OUTSTANDING_CHANNEL_REQUEST, ChannelStatus::InProgress)); channelResult = winrt::make(nullptr, WPN_E_OUTSTANDING_CHANNEL_REQUEST, ChannelStatus::CompletedFailure); co_return channelResult; } else { + s_lock.lock(); s_remoteIdList.push_back(remoteId); + s_lock.unlock(); } - s_lock.unlock(); PushNotificationChannelManager channelManager{}; + PushNotificationChannel pushChannel{ nullptr }; for (auto backOffTimeInSeconds = 30; backOffTimeInSeconds <= c_maxBackoffSeconds * 2; backOffTimeInSeconds *= 2) { try { - auto pushChannel = co_await channelManager.CreatePushNotificationChannelForApplicationAsync(); + + if (IsPackagedProcess()) + { + pushChannel = co_await channelManager.CreatePushNotificationChannelForApplicationAsync(); + } if (pushChannel != nullptr) { diff --git a/dev/PushNotifications/PushNotificationErrorCodes.h b/dev/PushNotifications/PushNotificationErrorCodes.h deleted file mode 100644 index 6522608947..0000000000 --- a/dev/PushNotifications/PushNotificationErrorCodes.h +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See LICENSE in the project root for license information. - -#pragma once - -namespace winrt::Microsoft::ProjectReunion::implementation -{ - enum WnpErrors - { - WNP_E_NOT_CONNECTED = 0x880403E8L, - WNP_E_RECONNECTING = 0x880403E9L, - WNP_E_BIND_USER_BUSY = 0x880403FEL, - }; -} diff --git a/dev/PushNotifications/PushNotifications.vcxitems b/dev/PushNotifications/PushNotifications.vcxitems index c1fc2a8c31..277e473f00 100644 --- a/dev/PushNotifications/PushNotifications.vcxitems +++ b/dev/PushNotifications/PushNotifications.vcxitems @@ -24,6 +24,5 @@ - \ No newline at end of file From cf7f238967d3696831f147210a3ef4b1019500ca Mon Sep 17 00:00:00 2001 From: Venkata Sharath Chandra Manchala Date: Mon, 8 Mar 2021 09:46:56 -0800 Subject: [PATCH 4/4] Make error codes internal to pushnotifications --- dev/PushNotifications/PushManager.cpp | 43 ++++++++++++++------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/dev/PushNotifications/PushManager.cpp b/dev/PushNotifications/PushManager.cpp index f23dbf7094..c4fae51174 100644 --- a/dev/PushNotifications/PushManager.cpp +++ b/dev/PushNotifications/PushManager.cpp @@ -13,19 +13,21 @@ #include using namespace winrt::Windows::Networking::PushNotifications; +using namespace winrt; namespace winrt::Microsoft::ProjectReunion::implementation { - std::vector PushManager::s_remoteIdList; + std::vector PushManager::s_remoteIdList; std::mutex PushManager::s_mutex; - std::unique_lock PushManager::s_lock (s_mutex, std::defer_lock); // Avoid locking during the constructor call + std::unique_lock PushManager::s_lock(s_mutex, std::defer_lock); // Avoid locking during the constructor call inline constexpr std::uint32_t c_maxBackoffSeconds{ 960 }; + inline constexpr std::uint32_t c_minBackoffSeconds{ 30 }; - const HRESULT WNP_E_NOT_CONNECTED = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x880403E8L); - const HRESULT WNP_E_RECONNECTING = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x880403E9L); - const HRESULT WNP_E_BIND_USER_BUSY = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x880403FEL); + const HRESULT WNP_E_NOT_CONNECTED = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WPN, 0x880403E8L); + const HRESULT WNP_E_RECONNECTING = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WPN, 0x880403E9L); + const HRESULT WNP_E_BIND_USER_BUSY = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WPN, 0x880403FEL); - bool PushManager::isChannelRequestRetryable(const winrt::hresult& hr) + bool PushManager::isChannelRequestRetryable(const hresult& hr) { switch (hr) { @@ -48,29 +50,29 @@ namespace winrt::Microsoft::ProjectReunion::implementation if (rc != ERROR_INSUFFICIENT_BUFFER) { - winrt::throw_hresult(rc); + throw_hresult(rc); } + return rc == ERROR_INSUFFICIENT_BUFFER; } - Windows::Foundation::IAsyncOperationWithProgress PushManager::CreateChannelAsync(winrt::guid remoteId) + Windows::Foundation::IAsyncOperationWithProgress PushManager::CreateChannelAsync(guid remoteId) { - winrt::Microsoft::ProjectReunion::ChannelResult channelResult{ nullptr }; - auto progress{ co_await winrt::get_progress_token() }; + Microsoft::ProjectReunion::ChannelResult channelResult{ nullptr }; + auto progress{ co_await get_progress_token() }; + + check_pointer(&remoteId); - winrt::check_pointer(&remoteId); - s_lock.lock(); if (std::find(s_remoteIdList.begin(), s_remoteIdList.end(), remoteId) != s_remoteIdList.end()) { s_lock.unlock(); - progress(winrt::make(nullptr, WPN_E_OUTSTANDING_CHANNEL_REQUEST, ChannelStatus::InProgress)); - channelResult = winrt::make(nullptr, WPN_E_OUTSTANDING_CHANNEL_REQUEST, ChannelStatus::CompletedFailure); + progress(make(nullptr, WPN_E_OUTSTANDING_CHANNEL_REQUEST, ChannelStatus::InProgress)); + channelResult = make(nullptr, WPN_E_OUTSTANDING_CHANNEL_REQUEST, ChannelStatus::CompletedFailure); co_return channelResult; } else { - s_lock.lock(); s_remoteIdList.push_back(remoteId); s_lock.unlock(); } @@ -78,11 +80,10 @@ namespace winrt::Microsoft::ProjectReunion::implementation PushNotificationChannelManager channelManager{}; PushNotificationChannel pushChannel{ nullptr }; - for (auto backOffTimeInSeconds = 30; backOffTimeInSeconds <= c_maxBackoffSeconds * 2; backOffTimeInSeconds *= 2) + for (auto backOffTimeInSeconds = c_minBackoffSeconds; backOffTimeInSeconds <= c_maxBackoffSeconds * 2; backOffTimeInSeconds *= 2) { try { - if (IsPackagedProcess()) { pushChannel = co_await channelManager.CreatePushNotificationChannelForApplicationAsync(); @@ -90,7 +91,7 @@ namespace winrt::Microsoft::ProjectReunion::implementation if (pushChannel != nullptr) { - channelResult = winrt::make(pushChannel, S_OK, ChannelStatus::CompletedSuccess); + channelResult = make(pushChannel, S_OK, ChannelStatus::CompletedSuccess); break; } } @@ -100,16 +101,16 @@ namespace winrt::Microsoft::ProjectReunion::implementation if ((backOffTimeInSeconds <= c_maxBackoffSeconds) && isChannelRequestRetryable(ex.code())) { - progress(winrt::make(nullptr, ex.code(), ChannelStatus::InProgressRetry)); + progress(make(nullptr, ex.code(), ChannelStatus::InProgressRetry)); } else { - channelResult = winrt::make(nullptr, ex.code(), ChannelStatus::CompletedFailure); + channelResult = make(nullptr, ex.code(), ChannelStatus::CompletedFailure); break; } } - co_await winrt::resume_after(std::chrono::seconds(backOffTimeInSeconds)); + co_await resume_after(std::chrono::seconds(backOffTimeInSeconds)); } s_lock.lock();