Updated network initializing detection (#457)

* Updated network initializing detection

* Feedback

* Feedback

* Improvements

* Build break
This commit is contained in:
Ramsey 2019-08-29 12:31:44 -07:00 коммит произвёл GitHub
Родитель e044384f62
Коммит f819ce02db
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
4 изменённых файлов: 85 добавлений и 38 удалений

Просмотреть файл

@ -433,12 +433,12 @@ typedef struct _LIST_ENTRY {
#define FACILITY_XBOX 2339
#define MAKE_E_HC(code) MAKE_HRESULT(1, FACILITY_XBOX, code)
#define E_HC_NOT_INITIALISED MAKE_E_HC(0x5001)
#define E_HC_PERFORM_ALREADY_CALLED MAKE_E_HC(0x5003)
#define E_HC_ALREADY_INITIALISED MAKE_E_HC(0x5004)
#define E_HC_CONNECT_ALREADY_CALLED MAKE_E_HC(0x5005)
#define E_HC_NO_NETWORK MAKE_E_HC(0x5006)
#define E_HC_NETWORK_NOT_READY MAKE_E_HC(0x5007)
#define E_HC_NOT_INITIALISED MAKE_E_HC(0x5001) // 0x89235001
#define E_HC_PERFORM_ALREADY_CALLED MAKE_E_HC(0x5003) // 0x89235003
#define E_HC_ALREADY_INITIALISED MAKE_E_HC(0x5004) // 0x89235004
#define E_HC_CONNECT_ALREADY_CALLED MAKE_E_HC(0x5005) // 0x89235005
#define E_HC_NO_NETWORK MAKE_E_HC(0x5006) // 0x89235006
#define E_HC_NETWORK_NOT_INITIALIZED MAKE_E_HC(0x5007) // 0x89235007
typedef uint32_t HCMemoryType;
typedef struct HC_WEBSOCKET* HCWebsocketHandle;

Просмотреть файл

@ -72,6 +72,11 @@ typedef struct http_singleton
uint32_t m_timeoutWindowInSeconds = DEFAULT_TIMEOUT_WINDOW_IN_SECONDS;
uint32_t m_retryDelayInSeconds = DEFAULT_RETRY_DELAY_IN_SECONDS;
#if HC_PLATFORM == HC_PLATFORM_GSDK
bool m_networkInitialized{ true };
HMODULE m_networkModule{ nullptr };
#endif
#if !HC_NOWEBSOCKETS
WebSocketPerformInfo const m_websocketPerform;
#endif

Просмотреть файл

@ -1038,6 +1038,22 @@ NAMESPACE_XBOX_HTTP_CLIENT_END
#if HC_PLATFORM == HC_PLATFORM_GSDK
typedef DWORD(WINAPI *GetNetworkConnectivityHintProc)(NL_NETWORK_CONNECTIVITY_HINT*);
typedef DWORD(WINAPI *NotifyNetworkConnectivityHintChangeProc)(PNETWORK_CONNECTIVITY_HINT_CHANGE_CALLBACK, PVOID, BOOLEAN, PHANDLE);
static void NetworkConnectivityHintChangedCallback(
_In_ void* context,
_In_ NL_NETWORK_CONNECTIVITY_HINT connectivityHint
)
{
UNREFERENCED_PARAMETER(context);
auto singleton = get_http_singleton(false);
if (singleton != nullptr)
{
singleton->m_networkInitialized = connectivityHint.ConnectivityLevel != NetworkConnectivityLevelHintUnknown;
}
}
#endif
HRESULT Internal_InitializeHttpPlatform(HCInitArgs* args, PerformEnv& performEnv) noexcept
@ -1045,36 +1061,6 @@ HRESULT Internal_InitializeHttpPlatform(HCInitArgs* args, PerformEnv& performEnv
assert(args == nullptr);
UNREFERENCED_PARAMETER(args);
#if HC_PLATFORM == HC_PLATFORM_GSDK
if (XGameRuntimeIsFeatureAvailable(XGameRuntimeFeature::XNetworking))
{
HMODULE hModule = LoadLibrary(TEXT("iphlpapi.dll"));
if (hModule != nullptr)
{
GetNetworkConnectivityHintProc getNetworkConnectivityHint =
(GetNetworkConnectivityHintProc)GetProcAddress(hModule, "GetNetworkConnectivityHint");
HRESULT hr = S_OK;
bool networkNotReady = false;
if (getNetworkConnectivityHint != nullptr)
{
NL_NETWORK_CONNECTIVITY_HINT connectivityHint{};
hr = HRESULT_FROM_WIN32(getNetworkConnectivityHint(&connectivityHint));
networkNotReady = connectivityHint.ConnectivityLevel == NetworkConnectivityLevelHintUnknown;
}
FreeLibrary(hModule);
if (SUCCEEDED(hr) && networkNotReady)
{
return E_HC_NETWORK_NOT_READY;
}
}
}
#endif
performEnv.reset(new (std::nothrow) HC_PERFORM_ENV());
if (!performEnv) { return E_OUTOFMEMORY; }
@ -1083,6 +1069,15 @@ HRESULT Internal_InitializeHttpPlatform(HCInitArgs* args, PerformEnv& performEnv
void Internal_CleanupHttpPlatform(HC_PERFORM_ENV* performEnv) noexcept
{
#if HC_PLATFORM == HC_PLATFORM_GSDK
auto singleton = get_http_singleton(false);
if (singleton != nullptr && singleton->m_networkModule != nullptr)
{
FreeLibrary(singleton->m_networkModule);
singleton->m_networkModule = nullptr;
}
#endif
delete performEnv;
}
@ -1154,6 +1149,51 @@ void CALLBACK Internal_HCHttpCallPerformAsync(
assert(env != nullptr);
UNREFERENCED_PARAMETER(context);
#if HC_PLATFORM == HC_PLATFORM_GSDK
if (XGameRuntimeIsFeatureAvailable(XGameRuntimeFeature::XNetworking))
{
auto singleton = get_http_singleton(true);
if (singleton != nullptr)
{
if (singleton->m_networkModule == nullptr)
{
singleton->m_networkModule = LoadLibrary(TEXT("iphlpapi.dll"));
if (singleton->m_networkModule != nullptr)
{
GetNetworkConnectivityHintProc getNetworkConnectivityHint =
(GetNetworkConnectivityHintProc)GetProcAddress(singleton->m_networkModule, "GetNetworkConnectivityHint");
NotifyNetworkConnectivityHintChangeProc notifyNetworkConnectivityHintChange =
(NotifyNetworkConnectivityHintChangeProc)GetProcAddress(singleton->m_networkModule, "NotifyNetworkConnectivityHintChange");
if (getNetworkConnectivityHint != nullptr && notifyNetworkConnectivityHintChange != nullptr)
{
NL_NETWORK_CONNECTIVITY_HINT connectivityHint{};
HRESULT hr = HRESULT_FROM_WIN32(getNetworkConnectivityHint(&connectivityHint));
singleton->m_networkInitialized = SUCCEEDED(hr) && connectivityHint.ConnectivityLevel != NetworkConnectivityLevelHintUnknown;
HANDLE networkConnectivityChangedHandle;
std::weak_ptr<http_singleton> singletonWeakPtr = singleton;
(void)HRESULT_FROM_WIN32(notifyNetworkConnectivityHintChange(
NetworkConnectivityHintChangedCallback,
nullptr,
TRUE,
&networkConnectivityChangedHandle));
}
}
}
if (!singleton->m_networkInitialized)
{
XAsyncComplete(asyncBlock, E_HC_NETWORK_NOT_INITIALIZED, 0);
return;
}
}
}
#endif
bool isWebsocket = false;
std::shared_ptr<xbox::httpclient::winhttp_http_task> httpTask = http_allocate_shared<winhttp_http_task>(
asyncBlock, call, env->m_hSession, env->m_proxyType, isWebsocket);

Просмотреть файл

@ -390,6 +390,8 @@ void retry_http_call_until_done(
return;
}
auto callStatus = XAsyncGetStatus(nestedAsyncBlock, false);
retry_context* retryContext = static_cast<retry_context*>(nestedAsyncBlock->context);
auto responseReceivedTime = chrono_clock_t::now();
@ -402,7 +404,7 @@ void retry_http_call_until_done(
}
delete nestedAsyncBlock;
if (http_call_should_retry(retryContext->call, responseReceivedTime))
if (SUCCEEDED(callStatus) && http_call_should_retry(retryContext->call, responseReceivedTime))
{
if (retryContext->call->traceCall) { HC_TRACE_INFORMATION(HTTPCLIENT, "HCHttpCallPerformExecute [ID %llu] Retry after %lld ms", retryContext->call->id, retryContext->call->delayBeforeRetry.count()); }
std::lock_guard<std::recursive_mutex> lock(httpSingleton->m_callRoutedHandlersLock);
@ -416,7 +418,7 @@ void retry_http_call_until_done(
}
else
{
XAsyncComplete(retryContext->outerAsyncBlock, S_OK, 0);
XAsyncComplete(retryContext->outerAsyncBlock, callStatus, 0);
}
};