193 lines
6.9 KiB
C++
193 lines
6.9 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "BackgroundHttpRequestImpl.h"
|
|
|
|
#include "BackgroundHttpModule.h"
|
|
#include "Interfaces/IBackgroundHttpResponse.h"
|
|
|
|
DEFINE_LOG_CATEGORY(LogBackgroundHttpRequest);
|
|
|
|
FBackgroundHttpRequestImpl::FBackgroundHttpRequestImpl()
|
|
: DownloadCompleteNotificationObject(nullptr)
|
|
, Response(nullptr)
|
|
, URLList()
|
|
, RequestID()
|
|
, NumberOfTotalRetries(0)
|
|
, RequestPriority(EBackgroundHTTPPriority::Normal)
|
|
, HttpRequestCompleteDelegate()
|
|
, HttpProgressUpdateDelegate()
|
|
{
|
|
}
|
|
|
|
bool FBackgroundHttpRequestImpl::ProcessRequest()
|
|
{
|
|
UE_LOG(LogBackgroundHttpRequest, Verbose, TEXT("Processing Request - RequestID:%s"), *GetRequestID());
|
|
FBackgroundHttpModule::Get().GetBackgroundHttpManager()->AddRequest(SharedThis(this));
|
|
|
|
return true;
|
|
}
|
|
|
|
void FBackgroundHttpRequestImpl::CancelRequest()
|
|
{
|
|
UE_LOG(LogBackgroundHttpRequest, Display, TEXT("Cancelling Request - RequestID:%s"), *GetRequestID());
|
|
FBackgroundHttpModule::Get().GetBackgroundHttpManager()->RemoveRequest(SharedThis(this));
|
|
}
|
|
|
|
void FBackgroundHttpRequestImpl::PauseRequest()
|
|
{
|
|
//for now a pause is just wrapping a cancel in the general case
|
|
UE_LOG(LogBackgroundHttpRequest, Display, TEXT("Pausing Request (through cancel) - RequestID:%s"), *GetRequestID());
|
|
CancelRequest();
|
|
}
|
|
|
|
void FBackgroundHttpRequestImpl::ResumeRequest()
|
|
{
|
|
//for now a resume is just wrapping a restart in the general case
|
|
UE_LOG(LogBackgroundHttpRequest, Display, TEXT("Resuming Request (through restart) - RequestID:%s"), *GetRequestID());
|
|
ProcessRequest();
|
|
}
|
|
|
|
void FBackgroundHttpRequestImpl::OnBackgroundDownloadComplete()
|
|
{
|
|
//The complete delegate should only be firing on the game thread
|
|
//so that requestors don't have to worry about thread safety unexpectedly
|
|
ensureAlwaysMsgf(IsInGameThread(), TEXT("Called from un-expected thread! Potential error in an implementation of background downloads!"));
|
|
|
|
FBackgroundHttpModule::Get().GetBackgroundHttpManager()->RemoveRequest(SharedThis(this));
|
|
|
|
//Determine if this was a success or not
|
|
FBackgroundHttpResponsePtr SetResponse = GetResponse();
|
|
const bool bWasSuccess = SetResponse.IsValid() ? EHttpResponseCodes::IsOk(SetResponse->GetResponseCode()) : false;
|
|
const FString ResponseTempLocation = Response.IsValid() ? Response->GetTempContentFilePath() : TEXT("None");
|
|
|
|
UE_LOG(LogBackgroundHttpRequest, Display, TEXT("Download Complete - RequestID:%s | bWasSuccess:%d | ResponseTempLocation:%s"), *GetRequestID(), (int)(bWasSuccess), *ResponseTempLocation);
|
|
|
|
//First, send a delegate out for this request completing
|
|
OnProcessRequestComplete().ExecuteIfBound(SharedThis(this), bWasSuccess);
|
|
|
|
//Second notify our download complete notification of the success/failure of this request. Then remove our reference
|
|
//so a notification will send without having to delete this request. Do this after Complete Delegate so we can ensure
|
|
//whatever kicked this off doesn't want to react to this download complete before we send this notification (IE: Kick off another download
|
|
//using the same NotificationObject, etc.)
|
|
NotifyNotificationObjectOfComplete(bWasSuccess);
|
|
|
|
//Now that we have called our completion delegates and done everything else for this request, allow us to clean up data for it
|
|
FBackgroundHttpModule::Get().GetBackgroundHttpManager()->CleanUpDataAfterCompletingRequest(SharedThis(this));
|
|
|
|
if (OptionalMetricsInfo.IsSet())
|
|
{
|
|
OnRequestMetrics().ExecuteIfBound(SharedThis(this), OptionalMetricsInfo->TotalBytesDownloaded, OptionalMetricsInfo->DownloadDuration);
|
|
OptionalMetricsInfo.Reset();
|
|
}
|
|
}
|
|
|
|
void FBackgroundHttpRequestImpl::NotifyNotificationObjectOfComplete(bool bWasSuccess)
|
|
{
|
|
// Get notification object and reset it (swap with nullptr)
|
|
TSharedPtr<FBackgroundHttpNotificationObject, ESPMode::ThreadSafe> LocalDownloadCompleteNotificationObject;
|
|
DownloadCompleteMutex.Lock();
|
|
Swap(DownloadCompleteNotificationObject, LocalDownloadCompleteNotificationObject);
|
|
DownloadCompleteMutex.Unlock();
|
|
|
|
if (LocalDownloadCompleteNotificationObject.IsValid())
|
|
{
|
|
LocalDownloadCompleteNotificationObject->NotifyOfDownloadResult(bWasSuccess);
|
|
}
|
|
}
|
|
|
|
void FBackgroundHttpRequestImpl::NotifyRequestMetricsAvailable(const int32 TotalBytesDownloaded, const float DownloadDuration)
|
|
{
|
|
OptionalMetricsInfo = {
|
|
.TotalBytesDownloaded = TotalBytesDownloaded,
|
|
.DownloadDuration = DownloadDuration
|
|
};
|
|
}
|
|
|
|
void FBackgroundHttpRequestImpl::SetURLAsList(const TArray<FString>& URLs, int NumRetriesIn)
|
|
{
|
|
NumberOfTotalRetries = NumRetriesIn;
|
|
for (const FString& URL : URLs)
|
|
{
|
|
URLList.Add(URL);
|
|
}
|
|
}
|
|
|
|
const TArray<FString>& FBackgroundHttpRequestImpl::GetURLList() const
|
|
{
|
|
return URLList;
|
|
}
|
|
|
|
void FBackgroundHttpRequestImpl::SetExpectedResultSize(const uint64 ExpectedSize)
|
|
{
|
|
ExpectedResultSize = ExpectedSize;
|
|
}
|
|
|
|
uint64 FBackgroundHttpRequestImpl::GetExpectedResultSize() const
|
|
{
|
|
return ExpectedResultSize;
|
|
}
|
|
|
|
void FBackgroundHttpRequestImpl::SetCompleteNotification(FBackgroundHttpNotificationObjectPtr DownloadCompleteNotificationObjectIn)
|
|
{
|
|
DownloadCompleteNotificationObject = DownloadCompleteNotificationObjectIn;
|
|
}
|
|
|
|
void FBackgroundHttpRequestImpl::CompleteWithExistingResponseData(FBackgroundHttpResponsePtr BackgroundResponse)
|
|
{
|
|
Response = BackgroundResponse;
|
|
|
|
const bool bHasValidResponse = Response.IsValid();
|
|
const FString ResponseTempLocation = Response.IsValid() ? Response->GetTempContentFilePath() : TEXT("None");
|
|
|
|
UE_LOG(LogBackgroundHttpRequest, Verbose, TEXT("Completing Download With Existing Response Data - RequestID:%s | bHasValidResponse:%d | ResponseTempDownloadLocation:%s"), *GetRequestID(), (int)(bHasValidResponse), *ResponseTempLocation);
|
|
|
|
OnBackgroundDownloadComplete();
|
|
}
|
|
|
|
FBackgroundHttpRequestCompleteDelegate& FBackgroundHttpRequestImpl::OnProcessRequestComplete()
|
|
{
|
|
return HttpRequestCompleteDelegate;
|
|
}
|
|
|
|
FBackgroundHttpProgressUpdateDelegate& FBackgroundHttpRequestImpl::OnProgressUpdated()
|
|
{
|
|
return HttpProgressUpdateDelegate;
|
|
}
|
|
|
|
FBackgroundHttpRequestMetricsDelegate& FBackgroundHttpRequestImpl::OnRequestMetrics()
|
|
{
|
|
return HttpRequestMetricsDelegate;
|
|
}
|
|
|
|
const FBackgroundHttpResponsePtr FBackgroundHttpRequestImpl::GetResponse() const
|
|
{
|
|
return Response;
|
|
}
|
|
|
|
const FString& FBackgroundHttpRequestImpl::GetRequestID() const
|
|
{
|
|
return RequestID;
|
|
}
|
|
|
|
void FBackgroundHttpRequestImpl::SetRequestID(const FString& NewRequestID)
|
|
{
|
|
RequestID = NewRequestID;
|
|
}
|
|
|
|
bool FBackgroundHttpRequestImpl::HandleDelayedProcess()
|
|
{
|
|
//By default we don't provide an implementation for this. If this is called, it should be overriden by the platform specific
|
|
//BackgroundHttpRequest if the platform expects to make use of this.
|
|
return ensureAlwaysMsgf(false, TEXT("Platform expects an implementation of HandleDelayedProcess on the BackgroundHttpRequest, but none found!"));
|
|
}
|
|
|
|
EBackgroundHTTPPriority FBackgroundHttpRequestImpl::GetRequestPriority() const
|
|
{
|
|
return RequestPriority;
|
|
}
|
|
|
|
void FBackgroundHttpRequestImpl::SetRequestPriority(EBackgroundHTTPPriority NewPriority)
|
|
{
|
|
RequestPriority = NewPriority;
|
|
}
|