|
|
@ -39,608 +39,401 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com |
|
|
|
Mead, WA 99021 |
|
|
|
Mead, WA 99021 |
|
|
|
|
|
|
|
|
|
|
|
*==LICENSE==*/ |
|
|
|
*==LICENSE==*/ |
|
|
|
#include "hsSTLStream.h" |
|
|
|
|
|
|
|
#include "hsResMgr.h" |
|
|
|
#include "pfSecurePreloader.h" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "hsStream.h" |
|
|
|
#include "plgDispatch.h" |
|
|
|
#include "plgDispatch.h" |
|
|
|
#include "pnUtils/pnUtils.h" |
|
|
|
#include "plCompression/plZlibStream.h" |
|
|
|
#include "pnNetBase/pnNetBase.h" |
|
|
|
#include "plEncryption/plChecksum.h" |
|
|
|
#include "pnAsyncCore/pnAsyncCore.h" |
|
|
|
|
|
|
|
#include "pnNetCli/pnNetCli.h" |
|
|
|
|
|
|
|
#include "plNetGameLib/plNetGameLib.h" |
|
|
|
|
|
|
|
#include "plFile/plFileUtils.h" |
|
|
|
#include "plFile/plFileUtils.h" |
|
|
|
|
|
|
|
#include "plFile/plSecureStream.h" |
|
|
|
#include "plFile/plStreamSource.h" |
|
|
|
#include "plFile/plStreamSource.h" |
|
|
|
#include "plNetCommon/plNetCommon.h" |
|
|
|
|
|
|
|
#include "plProgressMgr/plProgressMgr.h" |
|
|
|
|
|
|
|
#include "plMessage/plPreloaderMsg.h" |
|
|
|
|
|
|
|
#include "plMessage/plNetCommMsgs.h" |
|
|
|
#include "plMessage/plNetCommMsgs.h" |
|
|
|
#include "pfSecurePreloader.h" |
|
|
|
#include "plMessage/plPreloaderMsg.h" |
|
|
|
|
|
|
|
#include "plProgressMgr/plProgressMgr.h" |
|
|
|
#include "plNetClientComm/plNetClientComm.h" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
extern hsBool gDataServerLocal; |
|
|
|
extern hsBool gDataServerLocal; |
|
|
|
|
|
|
|
pfSecurePreloader* pfSecurePreloader::fInstance = nil; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
// Max number of concurrent file downloads
|
|
|
|
typedef std::pair<const wchar_t*, const wchar_t*> WcharPair; |
|
|
|
static const unsigned kMaxConcurrency = 1; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pfSecurePreloader * pfSecurePreloader::fInstance; |
|
|
|
struct AuthRequestParams |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
pfSecurePreloader* fThis; |
|
|
|
|
|
|
|
std::queue<WcharPair> fFileGroups; |
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
AuthRequestParams(pfSecurePreloader* parent) |
|
|
|
// Callback routines for the network code
|
|
|
|
: fThis(parent) { } |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// Called when a file's info is retrieved from the server
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
static void DefaultFileListRequestCallback(ENetError result, void* param, const NetCliAuthFileInfo infoArr[], unsigned infoCount) |
|
|
|
|
|
|
|
{ |
|
|
|
void ProcAuthDownloadParams(AuthRequestParams* params); |
|
|
|
bool success = !IS_NET_ERROR(result); |
|
|
|
|
|
|
|
|
|
|
|
void GotAuthSrvManifest( |
|
|
|
|
|
|
|
ENetError result, |
|
|
|
|
|
|
|
void* param, |
|
|
|
|
|
|
|
const NetCliAuthFileInfo infoArr[], |
|
|
|
|
|
|
|
UInt32 infoCount |
|
|
|
|
|
|
|
) { |
|
|
|
|
|
|
|
AuthRequestParams* arp = (AuthRequestParams*)param; |
|
|
|
|
|
|
|
if (IS_NET_ERROR(result)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
FATAL("Failed to get AuthSrv manifest!"); |
|
|
|
|
|
|
|
arp->fThis->Terminate(); |
|
|
|
|
|
|
|
delete arp; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
arp->fThis->PreloadManifest(infoArr, infoCount); |
|
|
|
|
|
|
|
ProcAuthDownloadParams(arp); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void GotFileSrvManifest( |
|
|
|
|
|
|
|
ENetError result,
|
|
|
|
|
|
|
|
void* param,
|
|
|
|
|
|
|
|
const wchar_t group[],
|
|
|
|
|
|
|
|
const NetCliFileManifestEntry manifest[],
|
|
|
|
|
|
|
|
UInt32 entryCount |
|
|
|
|
|
|
|
) { |
|
|
|
|
|
|
|
pfSecurePreloader* sp = (pfSecurePreloader*)param; |
|
|
|
|
|
|
|
if (result == kNetErrFileNotFound) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
AuthRequestParams* params = new AuthRequestParams(sp); |
|
|
|
|
|
|
|
params->fFileGroups.push(WcharPair(L"Python", L"pak")); |
|
|
|
|
|
|
|
params->fFileGroups.push(WcharPair(L"SDL", L"sdl")); |
|
|
|
|
|
|
|
ProcAuthDownloadParams(params); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} else if (!entryCount) { |
|
|
|
|
|
|
|
FATAL("SecurePreloader manifest empty!"); |
|
|
|
|
|
|
|
sp->Terminate(); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
std::vector<std::wstring> filenames; |
|
|
|
sp->PreloadManifest(manifest, entryCount); |
|
|
|
std::vector<UInt32> sizes; |
|
|
|
|
|
|
|
if (success) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
filenames.reserve(infoCount); |
|
|
|
|
|
|
|
sizes.reserve(infoCount); |
|
|
|
|
|
|
|
for (unsigned curFile = 0; curFile < infoCount; curFile++) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
filenames.push_back(infoArr[curFile].filename); |
|
|
|
|
|
|
|
sizes.push_back(infoArr[curFile].filesize); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void FileDownloaded( |
|
|
|
|
|
|
|
ENetError result, |
|
|
|
|
|
|
|
void* param, |
|
|
|
|
|
|
|
const wchar_t filename[], |
|
|
|
|
|
|
|
hsStream* writer |
|
|
|
|
|
|
|
) { |
|
|
|
|
|
|
|
pfSecurePreloader* sp = (pfSecurePreloader*)param; |
|
|
|
|
|
|
|
if (IS_NET_ERROR(result)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
FATAL("SecurePreloader download failed"); |
|
|
|
|
|
|
|
sp->Terminate(); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
sp->FilePreloaded(filename, writer); |
|
|
|
} |
|
|
|
} |
|
|
|
((pfSecurePreloader*)param)->RequestFinished(filenames, sizes, success); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Called when a file download is either finished, or failed
|
|
|
|
void ProcAuthDownloadParams(AuthRequestParams* params) |
|
|
|
static void DefaultFileRequestCallback(ENetError result, void* param, const wchar filename[], hsStream* stream) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
// Retry download unless shutting down or file not found
|
|
|
|
// Request the "manifests" until there are none left, then download the files
|
|
|
|
switch (result) { |
|
|
|
if (params->fFileGroups.empty()) |
|
|
|
case kNetSuccess: |
|
|
|
{ |
|
|
|
((pfSecurePreloader*)param)->FinishedDownload(filename, true); |
|
|
|
params->fThis->PreloadNextFile(); |
|
|
|
break; |
|
|
|
delete params; |
|
|
|
|
|
|
|
} else { |
|
|
|
case kNetErrFileNotFound: |
|
|
|
WcharPair wp = params->fFileGroups.front(); |
|
|
|
case kNetErrRemoteShutdown: |
|
|
|
params->fFileGroups.pop(); |
|
|
|
((pfSecurePreloader*)param)->FinishedDownload(filename, false); |
|
|
|
NetCliAuthFileListRequest(wp.first, wp.second, GotAuthSrvManifest, params); |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
stream->Rewind(); |
|
|
|
|
|
|
|
NetCliAuthFileRequest( |
|
|
|
|
|
|
|
filename, |
|
|
|
|
|
|
|
stream,
|
|
|
|
|
|
|
|
&DefaultFileRequestCallback, |
|
|
|
|
|
|
|
param |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
class pfSecurePreloaderStream : public plZlibStream |
|
|
|
// Our custom stream for writing directly to disk securely, and updating the
|
|
|
|
|
|
|
|
// progress bar. Does NOT support reading (cause it doesn't need to)
|
|
|
|
|
|
|
|
class Direct2DiskStream : public hsUNIXStream |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
protected: |
|
|
|
plOperationProgress* fProgress; |
|
|
|
wchar * fWriteFileName; |
|
|
|
bool fIsZipped; |
|
|
|
|
|
|
|
|
|
|
|
pfSecurePreloader* fPreloader; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public: |
|
|
|
public: |
|
|
|
Direct2DiskStream(pfSecurePreloader* preloader); |
|
|
|
|
|
|
|
~Direct2DiskStream(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
virtual hsBool Open(const char* name, const char* mode = "wb"); |
|
|
|
|
|
|
|
virtual hsBool Open(const wchar* name, const wchar* mode = L"wb"); |
|
|
|
|
|
|
|
virtual hsBool Close(); |
|
|
|
|
|
|
|
virtual UInt32 Read(UInt32 byteCount, void* buffer); |
|
|
|
|
|
|
|
virtual UInt32 Write(UInt32 byteCount, const void* buffer); |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Direct2DiskStream::Direct2DiskStream(pfSecurePreloader* preloader) : |
|
|
|
|
|
|
|
fWriteFileName(nil), |
|
|
|
|
|
|
|
fPreloader(preloader) |
|
|
|
|
|
|
|
{} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Direct2DiskStream::~Direct2DiskStream() |
|
|
|
pfSecurePreloaderStream(plOperationProgress* prog, bool zipped) |
|
|
|
|
|
|
|
: fProgress(prog), fIsZipped(zipped), plZlibStream() |
|
|
|
{
|
|
|
|
{
|
|
|
|
Close(); |
|
|
|
fOutput = new hsRAMStream; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
hsBool Direct2DiskStream::Open(const char* name, const char* mode) |
|
|
|
~pfSecurePreloaderStream() |
|
|
|
{ |
|
|
|
{ |
|
|
|
wchar* wName = hsStringToWString(name); |
|
|
|
delete fOutput; |
|
|
|
wchar* wMode = hsStringToWString(mode); |
|
|
|
fOutput = nil; |
|
|
|
hsBool ret = Open(wName, wMode); |
|
|
|
plZlibStream::Close(); |
|
|
|
delete [] wName; |
|
|
|
|
|
|
|
delete [] wMode; |
|
|
|
|
|
|
|
return ret; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
hsBool Direct2DiskStream::Open(const wchar* name, const wchar* mode) |
|
|
|
hsBool AtEnd() { return fOutput->AtEnd(); } |
|
|
|
|
|
|
|
UInt32 GetEOF() { return fOutput->GetEOF(); } |
|
|
|
|
|
|
|
UInt32 GetPosition() const { return fOutput->GetPosition(); } |
|
|
|
|
|
|
|
UInt32 GetSizeLeft() const { return fOutput->GetSizeLeft(); } |
|
|
|
|
|
|
|
UInt32 Read(UInt32 count, void* buf) { return fOutput->Read(count, buf); } |
|
|
|
|
|
|
|
void Rewind() { fOutput->Rewind(); } |
|
|
|
|
|
|
|
void SetPosition(UInt32 pos) { fOutput->SetPosition(pos); } |
|
|
|
|
|
|
|
void Skip(UInt32 deltaByteCount) { fOutput->Skip(deltaByteCount); } |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
UInt32 Write(UInt32 count, const void* buf) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (0 != wcscmp(mode, L"wb")) { |
|
|
|
if (fProgress) |
|
|
|
hsAssert(0, "Unsupported open mode"); |
|
|
|
fProgress->Increment((hsScalar)count); |
|
|
|
return false; |
|
|
|
if (fIsZipped) |
|
|
|
|
|
|
|
return plZlibStream::Write(count, buf); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
return fOutput->Write(count, buf); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
fWriteFileName = TRACKED_NEW(wchar[wcslen(name) + 1]); |
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
wcscpy(fWriteFileName, name); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// LogMsg(kLogPerf, L"Opening disk file %S", fWriteFileName);
|
|
|
|
pfSecurePreloader::pfSecurePreloader() |
|
|
|
return hsUNIXStream::Open(name, mode); |
|
|
|
: fProgress(nil), fLegacyMode(false) |
|
|
|
} |
|
|
|
{ } |
|
|
|
|
|
|
|
|
|
|
|
hsBool Direct2DiskStream::Close() |
|
|
|
pfSecurePreloader::~pfSecurePreloader() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
while (fDownloadEntries.size()) |
|
|
|
{ |
|
|
|
{ |
|
|
|
delete [] fWriteFileName; |
|
|
|
free((void*)fDownloadEntries.front()); |
|
|
|
fWriteFileName = nil; |
|
|
|
fDownloadEntries.pop(); |
|
|
|
return hsUNIXStream::Close(); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
UInt32 Direct2DiskStream::Read(UInt32 bytes, void* buffer) |
|
|
|
while (fManifestEntries.size()) |
|
|
|
{ |
|
|
|
{ |
|
|
|
hsAssert(0, "not implemented"); |
|
|
|
free((void*)fManifestEntries.front()); |
|
|
|
return 0; // we don't read
|
|
|
|
fManifestEntries.pop(); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
UInt32 Direct2DiskStream::Write(UInt32 bytes, const void* buffer) |
|
|
|
hsRAMStream* pfSecurePreloader::LoadToMemory(const wchar_t* file) const |
|
|
|
{ |
|
|
|
{ |
|
|
|
// LogMsg(kLogPerf, L"Writing %u bytes to disk file %S", bytes, fWriteFileName);
|
|
|
|
if (!plFileUtils::FileExists(file)) |
|
|
|
fPreloader->UpdateProgressBar(bytes); |
|
|
|
return nil; |
|
|
|
return hsUNIXStream::Write(bytes, buffer); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hsUNIXStream s; |
|
|
|
|
|
|
|
hsRAMStream* ram = new hsRAMStream; |
|
|
|
|
|
|
|
s.Open(file); |
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
UInt32 loadLen = 1024 * 1024; |
|
|
|
// secure preloader class implementation
|
|
|
|
UInt8* buf = new UInt8[loadLen]; |
|
|
|
|
|
|
|
while (UInt32 read = s.Read(loadLen, buf)) |
|
|
|
|
|
|
|
ram->Write(read, buf); |
|
|
|
|
|
|
|
delete[] buf; |
|
|
|
|
|
|
|
|
|
|
|
// closes and deletes all streams
|
|
|
|
s.Close(); |
|
|
|
void pfSecurePreloader::ICleanupStreams() |
|
|
|
ram->Rewind(); |
|
|
|
{ |
|
|
|
return ram; |
|
|
|
if (fD2DStreams.size() > 0) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
std::map<std::wstring, hsStream*>::iterator curStream; |
|
|
|
|
|
|
|
for (curStream = fD2DStreams.begin(); curStream != fD2DStreams.end(); curStream++) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
curStream->second->Close(); |
|
|
|
|
|
|
|
delete curStream->second; |
|
|
|
|
|
|
|
curStream->second = nil; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
fD2DStreams.clear(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// queues a single file to be preloaded (does nothing if already preloaded)
|
|
|
|
void pfSecurePreloader::SaveFile(hsStream* file, const wchar_t* name) const |
|
|
|
void pfSecurePreloader::RequestSingleFile(std::wstring filename) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
fileRequest request; |
|
|
|
hsUNIXStream s; |
|
|
|
ZERO(request); |
|
|
|
s.Open(name, L"wb"); |
|
|
|
request.fType = fileRequest::kSingleFile; |
|
|
|
UInt32 pos = file->GetPosition(); |
|
|
|
request.fPath = filename; |
|
|
|
file->Rewind(); |
|
|
|
request.fExt = L""; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fRequests.push_back(request); |
|
|
|
UInt32 loadLen = 1024 * 1024; |
|
|
|
|
|
|
|
UInt8* buf = new UInt8[loadLen]; |
|
|
|
|
|
|
|
while (UInt32 read = file->Read(loadLen, buf)) |
|
|
|
|
|
|
|
s.Write(read, buf); |
|
|
|
|
|
|
|
file->SetPosition(pos); |
|
|
|
|
|
|
|
s.Close(); |
|
|
|
|
|
|
|
delete[] buf; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// queues a group of files to be preloaded (does nothing if already preloaded)
|
|
|
|
bool pfSecurePreloader::IsZipped(const wchar_t* filename) const |
|
|
|
void pfSecurePreloader::RequestFileGroup(std::wstring dir, std::wstring ext) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
fileRequest request; |
|
|
|
return wcscmp(plFileUtils::GetFileExt(filename), L"gz") == 0; |
|
|
|
ZERO(request); |
|
|
|
|
|
|
|
request.fType = fileRequest::kFileList; |
|
|
|
|
|
|
|
request.fPath = dir; |
|
|
|
|
|
|
|
request.fExt = ext; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fRequests.push_back(request); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// preloads all requested files from the server (does nothing if already preloaded)
|
|
|
|
void pfSecurePreloader::PreloadNextFile() |
|
|
|
void pfSecurePreloader::Start() |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
if (gDataServerLocal) { |
|
|
|
if (fManifestEntries.empty()) |
|
|
|
// using local data, don't do anything
|
|
|
|
{ |
|
|
|
plPreloaderMsg * msg = TRACKED_NEW plPreloaderMsg(); |
|
|
|
Finish(); |
|
|
|
msg->fSuccess = true; |
|
|
|
|
|
|
|
msg->Send(); |
|
|
|
|
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
NetCliAuthGetEncryptionKey(fEncryptionKey, 4); // grab the encryption key from the server
|
|
|
|
const wchar_t* filename = fDownloadEntries.front(); |
|
|
|
|
|
|
|
hsStream* s = new pfSecurePreloaderStream(fProgress, IsZipped(filename)); |
|
|
|
|
|
|
|
|
|
|
|
fNetError = false; |
|
|
|
// Thankfully, both callbacks have the same arguments
|
|
|
|
|
|
|
|
if (fLegacyMode) |
|
|
|
// make sure we are all cleaned up
|
|
|
|
NetCliAuthFileRequest(filename, s, FileDownloaded, this); |
|
|
|
ICleanupStreams(); |
|
|
|
else |
|
|
|
fTotalDataReceived = 0; |
|
|
|
NetCliFileDownloadRequest(filename, s, FileDownloaded, this); |
|
|
|
|
|
|
|
} |
|
|
|
// update the progress bar for downloading
|
|
|
|
|
|
|
|
if (!fProgressBar) |
|
|
|
|
|
|
|
fProgressBar = plProgressMgr::GetInstance()->RegisterOperation((hsScalar)(fRequests.size()), "Getting file info...", plProgressMgr::kUpdateText, false, true); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (unsigned curRequest = 0; curRequest < fRequests.size(); curRequest++) |
|
|
|
void pfSecurePreloader::Init() |
|
|
|
{ |
|
|
|
|
|
|
|
fNumInfoRequestsRemaining++; // increment the counter
|
|
|
|
|
|
|
|
if (fRequests[curRequest].fType == fileRequest::kSingleFile) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
#ifndef PLASMA_EXTERNAL_RELEASE |
|
|
|
RegisterAs(kSecurePreloader_KEY); |
|
|
|
// in internal releases, we can use on-disk files if they exist
|
|
|
|
// TODO: If we're going to support reconnects, then let's do it right.
|
|
|
|
if (plFileUtils::FileExists(fRequests[curRequest].fPath.c_str())) |
|
|
|
// Later...
|
|
|
|
{ |
|
|
|
//plgDispatch::Dispatch()->RegisterForExactType(plNetCommAuthConnectedMsg::Index(), GetKey());
|
|
|
|
fileInfo info; |
|
|
|
|
|
|
|
info.fOriginalNameAndPath = fRequests[curRequest].fPath; |
|
|
|
|
|
|
|
info.fSizeInBytes = plFileUtils::GetFileSize(info.fOriginalNameAndPath.c_str()); |
|
|
|
|
|
|
|
info.fDownloading = false; |
|
|
|
|
|
|
|
info.fDownloaded = false; |
|
|
|
|
|
|
|
info.fLocal = true; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// generate garbled name
|
|
|
|
|
|
|
|
wchar_t pathBuffer[MAX_PATH + 1]; |
|
|
|
|
|
|
|
wchar_t filename[arrsize(pathBuffer)]; |
|
|
|
|
|
|
|
GetTempPathW(arrsize(pathBuffer), pathBuffer); |
|
|
|
|
|
|
|
GetTempFileNameW(pathBuffer, L"CYN", 0, filename); |
|
|
|
|
|
|
|
info.fGarbledNameAndPath = filename; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fTotalDataDownload += info.fSizeInBytes; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fFileInfoMap[info.fOriginalNameAndPath] = info; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// internal client will still request it, even if it exists locally,
|
|
|
|
|
|
|
|
// so that things get updated properly
|
|
|
|
|
|
|
|
#endif // PLASMA_EXTERNAL_RELEASE
|
|
|
|
|
|
|
|
NetCliAuthFileListRequest( |
|
|
|
|
|
|
|
fRequests[curRequest].fPath.c_str(), |
|
|
|
|
|
|
|
nil, |
|
|
|
|
|
|
|
&DefaultFileListRequestCallback, |
|
|
|
|
|
|
|
(void*)this |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
|
|
|
|
|
|
|
|
void pfSecurePreloader::Start() |
|
|
|
{ |
|
|
|
{ |
|
|
|
#ifndef PLASMA_EXTERNAL_RELEASE |
|
|
|
#ifndef PLASMA_EXTERNAL_RELEASE |
|
|
|
// in internal releases, we can use on-disk files if they exist
|
|
|
|
// Using local data? Move along, move along...
|
|
|
|
// Build the search string as "dir\\*.ext"
|
|
|
|
if (gDataServerLocal) |
|
|
|
wchar searchStr[MAX_PATH]; |
|
|
|
{ |
|
|
|
|
|
|
|
Finish(); |
|
|
|
PathAddFilename(searchStr, fRequests[curRequest].fPath.c_str(), L"*", arrsize(searchStr)); |
|
|
|
return; |
|
|
|
PathSetExtension(searchStr, searchStr, fRequests[curRequest].fExt.c_str(), arrsize(searchStr)); |
|
|
|
} |
|
|
|
|
|
|
|
#endif |
|
|
|
ARRAY(PathFind) paths; |
|
|
|
|
|
|
|
PathFindFiles(&paths, searchStr, kPathFlagFile); // find all files that match
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// convert it to our little file info array
|
|
|
|
|
|
|
|
PathFind* curFile = paths.Ptr(); |
|
|
|
|
|
|
|
PathFind* lastFile = paths.Term(); |
|
|
|
|
|
|
|
while (curFile != lastFile) { |
|
|
|
|
|
|
|
fileInfo info; |
|
|
|
|
|
|
|
info.fOriginalNameAndPath = curFile->name; |
|
|
|
|
|
|
|
info.fSizeInBytes = (UInt32)curFile->fileLength; |
|
|
|
|
|
|
|
info.fDownloading = false; |
|
|
|
|
|
|
|
info.fDownloaded = false; |
|
|
|
|
|
|
|
info.fLocal = true; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// generate garbled name
|
|
|
|
NetCliAuthGetEncryptionKey(fEncryptionKey, 4); |
|
|
|
wchar_t pathBuffer[MAX_PATH + 1]; |
|
|
|
|
|
|
|
wchar_t filename[arrsize(pathBuffer)]; |
|
|
|
|
|
|
|
GetTempPathW(arrsize(pathBuffer), pathBuffer); |
|
|
|
|
|
|
|
GetTempFileNameW(pathBuffer, L"CYN", 0, filename); |
|
|
|
|
|
|
|
info.fGarbledNameAndPath = filename; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fTotalDataDownload += info.fSizeInBytes; |
|
|
|
// TODO: Localize
|
|
|
|
|
|
|
|
fProgress = plProgressMgr::GetInstance()->RegisterOperation(0.0f, "Checking for Updates", plProgressMgr::kUpdateText, false, true); |
|
|
|
|
|
|
|
|
|
|
|
fFileInfoMap[info.fOriginalNameAndPath] = info; |
|
|
|
// Now, we need to fetch the "SecurePreloader" manifest from the file server, which will contain the python and SDL files.
|
|
|
|
curFile++; |
|
|
|
// We're basically reimplementing plResPatcher here, except preferring to keep everything in memory, then flush to disk
|
|
|
|
|
|
|
|
// when we're done. If this fails, then we shall download everything from the AuthSrv like in the old days.
|
|
|
|
|
|
|
|
NetCliFileManifestRequest(GotFileSrvManifest, this, L"SecurePreloader"); |
|
|
|
} |
|
|
|
} |
|
|
|
#endif // PLASMA_EXTERNAL_RELEASE
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NetCliAuthFileListRequest( |
|
|
|
void pfSecurePreloader::Terminate() |
|
|
|
fRequests[curRequest].fPath.c_str(), |
|
|
|
|
|
|
|
fRequests[curRequest].fExt.c_str(), |
|
|
|
|
|
|
|
&DefaultFileListRequestCallback, |
|
|
|
|
|
|
|
(void*)this |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// closes all file pointers and cleans up after itself
|
|
|
|
|
|
|
|
void pfSecurePreloader::Cleanup() |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
ICleanupStreams(); |
|
|
|
FATAL("pfSecurePreloader failure"); |
|
|
|
|
|
|
|
|
|
|
|
fRequests.clear(); |
|
|
|
|
|
|
|
fFileInfoMap.clear(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fNumInfoRequestsRemaining = 0; |
|
|
|
|
|
|
|
fTotalDataDownload = 0; |
|
|
|
|
|
|
|
fTotalDataReceived = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DEL(fProgressBar); |
|
|
|
plPreloaderMsg* msg = new plPreloaderMsg; |
|
|
|
fProgressBar = nil; |
|
|
|
msg->fSuccess = false; |
|
|
|
|
|
|
|
plgDispatch::Dispatch()->MsgSend(msg); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
void pfSecurePreloader::Finish() |
|
|
|
void pfSecurePreloader::RequestFinished(const std::vector<std::wstring> & filenames, const std::vector<UInt32> & sizes, bool succeeded) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
fNetError |= !succeeded; |
|
|
|
plPreloaderMsg* msg = new plPreloaderMsg; |
|
|
|
|
|
|
|
msg->fSuccess = true; |
|
|
|
|
|
|
|
plgDispatch::Dispatch()->MsgSend(msg); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (succeeded) |
|
|
|
void pfSecurePreloader::Shutdown() |
|
|
|
{ |
|
|
|
{ |
|
|
|
unsigned count = 0; |
|
|
|
SetInstance(nil); |
|
|
|
for (int curFile = 0; curFile < filenames.size(); curFile++) |
|
|
|
if (fProgress) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (fFileInfoMap.find(filenames[curFile]) != fFileInfoMap.end()) |
|
|
|
delete fProgress; |
|
|
|
continue; // if it is a duplicate, ignore it (the duplicate is probably one we found locally)
|
|
|
|
fProgress = nil; |
|
|
|
|
|
|
|
|
|
|
|
fileInfo info; |
|
|
|
|
|
|
|
info.fOriginalNameAndPath = filenames[curFile]; |
|
|
|
|
|
|
|
info.fSizeInBytes = sizes[curFile]; |
|
|
|
|
|
|
|
info.fDownloading = false; |
|
|
|
|
|
|
|
info.fDownloaded = false; |
|
|
|
|
|
|
|
info.fLocal = false; // if we get here, it was retrieved remotely
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// generate garbled name
|
|
|
|
|
|
|
|
wchar_t pathBuffer[MAX_PATH + 1]; |
|
|
|
|
|
|
|
wchar_t filename[arrsize(pathBuffer)]; |
|
|
|
|
|
|
|
GetTempPathW(arrsize(pathBuffer), pathBuffer); |
|
|
|
|
|
|
|
GetTempFileNameW(pathBuffer, L"CYN", 0, filename); |
|
|
|
|
|
|
|
info.fGarbledNameAndPath = filename; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fTotalDataDownload += info.fSizeInBytes; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fFileInfoMap[info.fOriginalNameAndPath] = info; |
|
|
|
|
|
|
|
++count; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
LogMsg(kLogPerf, "Added %u files to secure download queue", count); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
if (fProgressBar) |
|
|
|
|
|
|
|
fProgressBar->Increment(1.f); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
--fNumInfoRequestsRemaining; // even if we fail, decrement the counter
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (succeeded) { |
|
|
|
|
|
|
|
DEL(fProgressBar); |
|
|
|
|
|
|
|
fProgressBar = plProgressMgr::GetInstance()->RegisterOperation((hsScalar)(fTotalDataDownload), "Downloading...", plProgressMgr::kUpdateText, false, true); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Issue some file download requests (up to kMaxConcurrency)
|
|
|
|
// Takes care of UnReffing us
|
|
|
|
IIssueDownloadRequests(); |
|
|
|
UnRegisterAs(kSecurePreloader_KEY); |
|
|
|
} |
|
|
|
|
|
|
|
else { |
|
|
|
|
|
|
|
IPreloadComplete(); |
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
void pfSecurePreloader::PreloadManifest(const NetCliAuthFileInfo manifestEntries[], UInt32 entryCount) |
|
|
|
void pfSecurePreloader::IIssueDownloadRequests () { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::map<std::wstring, fileInfo>::iterator curFile; |
|
|
|
|
|
|
|
for (curFile = fFileInfoMap.begin(); curFile != fFileInfoMap.end(); curFile++) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
// Skip files already downloaded or currently downloading
|
|
|
|
UInt32 totalBytes = 0; |
|
|
|
if (curFile->second.fDownloaded || curFile->second.fDownloading) |
|
|
|
if (fProgress) |
|
|
|
continue; |
|
|
|
totalBytes = (UInt32)fProgress->GetMax(); |
|
|
|
|
|
|
|
fLegacyMode = true; |
|
|
|
|
|
|
|
|
|
|
|
std::wstring filename = curFile->second.fOriginalNameAndPath; |
|
|
|
for (UInt32 i = 0; i < entryCount; ++i) |
|
|
|
#ifndef PLASMA_EXTERNAL_RELEASE |
|
|
|
|
|
|
|
// in internal releases, we can use on-disk files if they exist
|
|
|
|
|
|
|
|
if (plFileUtils::FileExists(filename.c_str())) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
// don't bother streaming, just make the secure stream using the local file
|
|
|
|
const NetCliAuthFileInfo mfs = manifestEntries[i]; |
|
|
|
|
|
|
|
fDownloadEntries.push(wcsdup(mfs.filename)); |
|
|
|
// a local key overrides the server-downloaded key
|
|
|
|
if (IsZipped(mfs.filename)) |
|
|
|
UInt32 localKey[4]; |
|
|
|
|
|
|
|
bool hasLocalKey = plFileUtils::GetSecureEncryptionKey(filename.c_str(), localKey, arrsize(localKey)); |
|
|
|
|
|
|
|
hsStream* stream = nil; |
|
|
|
|
|
|
|
if (hasLocalKey) |
|
|
|
|
|
|
|
stream = plSecureStream::OpenSecureFile(filename.c_str(), 0, localKey); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
stream = plSecureStream::OpenSecureFile(filename.c_str(), 0, fEncryptionKey); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// add it to the stream source
|
|
|
|
|
|
|
|
bool added = plStreamSource::GetInstance()->InsertFile(filename.c_str(), stream); |
|
|
|
|
|
|
|
if (!added) |
|
|
|
|
|
|
|
DEL(stream); // wasn't added, so nuke our local copy
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// and make sure the vars are set up right
|
|
|
|
|
|
|
|
curFile->second.fDownloaded = true; |
|
|
|
|
|
|
|
curFile->second.fLocal = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
// Enforce concurrency limit
|
|
|
|
wchar_t* name = wcsdup(mfs.filename); |
|
|
|
if (fNumDownloadRequestsRemaining >= kMaxConcurrency) |
|
|
|
plFileUtils::StripExt(name); |
|
|
|
break; |
|
|
|
fManifestEntries.push(name); |
|
|
|
|
|
|
|
|
|
|
|
curFile->second.fDownloading = true; |
|
|
|
} else |
|
|
|
curFile->second.fDownloaded = false; |
|
|
|
fManifestEntries.push(wcsdup(mfs.filename)); |
|
|
|
curFile->second.fLocal = false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// create and setup the stream
|
|
|
|
totalBytes += mfs.filesize; |
|
|
|
Direct2DiskStream* fileStream = TRACKED_NEW Direct2DiskStream(this); |
|
|
|
|
|
|
|
fileStream->Open(curFile->second.fGarbledNameAndPath.c_str(), L"wb"); |
|
|
|
|
|
|
|
fD2DStreams[filename] = (hsStream*)fileStream; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// request the file from the server
|
|
|
|
|
|
|
|
LogMsg(kLogPerf, L"Requesting secure file:%s", filename.c_str()); |
|
|
|
|
|
|
|
++fNumDownloadRequestsRemaining; |
|
|
|
|
|
|
|
NetCliAuthFileRequest( |
|
|
|
|
|
|
|
filename.c_str(), |
|
|
|
|
|
|
|
(hsStream*)fileStream,
|
|
|
|
|
|
|
|
&DefaultFileRequestCallback, |
|
|
|
|
|
|
|
this |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (!fNumDownloadRequestsRemaining) |
|
|
|
if (fProgress) |
|
|
|
IPreloadComplete(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void pfSecurePreloader::UpdateProgressBar(UInt32 bytesReceived) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
fTotalDataReceived += bytesReceived; |
|
|
|
fProgress->SetLength((hsScalar)totalBytes); |
|
|
|
if (fTotalDataReceived > fTotalDataDownload) |
|
|
|
fProgress->SetTitle("Downloading..."); |
|
|
|
fTotalDataReceived = fTotalDataDownload; // shouldn't happen... but just in case
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (fProgressBar) |
|
|
|
|
|
|
|
fProgressBar->Increment((hsScalar)bytesReceived); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void pfSecurePreloader::FinishedDownload(std::wstring filename, bool succeeded) |
|
|
|
void pfSecurePreloader::PreloadManifest(const NetCliFileManifestEntry manifestEntries[], UInt32 entryCount) |
|
|
|
{ |
|
|
|
|
|
|
|
for (;;) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
if (fFileInfoMap.find(filename) == fFileInfoMap.end()) |
|
|
|
UInt32 totalBytes = 0; |
|
|
|
|
|
|
|
for (UInt32 i = 0; i < entryCount; ++i) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// file doesn't exist... abort
|
|
|
|
const NetCliFileManifestEntry mfs = manifestEntries[i]; |
|
|
|
succeeded = false; |
|
|
|
bool fetchMe = true; |
|
|
|
break; |
|
|
|
hsRAMStream* s = nil; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fFileInfoMap[filename].fDownloading = false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// close and delete the writer stream (even if we failed)
|
|
|
|
if (plFileUtils::FileExists(mfs.clientName)) |
|
|
|
fD2DStreams[filename]->Close(); |
|
|
|
|
|
|
|
delete fD2DStreams[filename]; |
|
|
|
|
|
|
|
fD2DStreams.erase(fD2DStreams.find(filename)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (succeeded) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
// open a secure stream to that file
|
|
|
|
s = LoadToMemory(mfs.clientName); |
|
|
|
hsStream* stream = plSecureStream::OpenSecureFile( |
|
|
|
if (s) |
|
|
|
fFileInfoMap[filename].fGarbledNameAndPath.c_str(), |
|
|
|
{ |
|
|
|
plSecureStream::kRequireEncryption | plSecureStream::kDeleteOnExit, // force delete and encryption
|
|
|
|
// Damn this
|
|
|
|
fEncryptionKey |
|
|
|
const char* md5 = hsWStringToString(mfs.md5); |
|
|
|
); |
|
|
|
plMD5Checksum srvHash; |
|
|
|
|
|
|
|
srvHash.SetFromHexString(md5); |
|
|
|
bool addedToSource = plStreamSource::GetInstance()->InsertFile(filename.c_str(), stream); |
|
|
|
delete[] md5; |
|
|
|
if (!addedToSource) |
|
|
|
|
|
|
|
DEL(stream); // cleanup if it wasn't added
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fFileInfoMap[filename].fDownloaded = true; |
|
|
|
// Now actually copare the hashes
|
|
|
|
break; |
|
|
|
plMD5Checksum lclHash; |
|
|
|
|
|
|
|
lclHash.CalcFromStream(s); |
|
|
|
|
|
|
|
fetchMe = (srvHash != lclHash); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// file download failed, clean up after it
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// delete the temporary file
|
|
|
|
|
|
|
|
if (plFileUtils::FileExists(fFileInfoMap[filename].fGarbledNameAndPath.c_str())) |
|
|
|
|
|
|
|
plFileUtils::RemoveFile(fFileInfoMap[filename].fGarbledNameAndPath.c_str(), true); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// and remove it from the info map
|
|
|
|
|
|
|
|
fFileInfoMap.erase(fFileInfoMap.find(filename)); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fNetError |= !succeeded; |
|
|
|
if (fetchMe) |
|
|
|
--fNumDownloadRequestsRemaining; |
|
|
|
{ |
|
|
|
LogMsg(kLogPerf, L"Received secure file:%s, success:%s", filename.c_str(), succeeded ? L"Yep" : L"Nope"); |
|
|
|
fManifestEntries.push(wcsdup(mfs.clientName)); |
|
|
|
|
|
|
|
fDownloadEntries.push(wcsdup(mfs.downloadName)); |
|
|
|
if (!succeeded) |
|
|
|
if (IsZipped(mfs.downloadName)) |
|
|
|
IPreloadComplete(); |
|
|
|
totalBytes += mfs.zipSize; |
|
|
|
else |
|
|
|
else |
|
|
|
// Issue some file download requests (up to kMaxConcurrency)
|
|
|
|
totalBytes += mfs.fileSize; |
|
|
|
IIssueDownloadRequests(); |
|
|
|
} else { |
|
|
|
|
|
|
|
plSecureStream* ss = new plSecureStream(s, fEncryptionKey); |
|
|
|
|
|
|
|
plStreamSource::GetInstance()->InsertFile(mfs.clientName, ss); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
if (s) |
|
|
|
void pfSecurePreloader::INotifyAuthReconnected () { |
|
|
|
delete s; |
|
|
|
|
|
|
|
|
|
|
|
// The secure file download network protocol will now just pick up downloading
|
|
|
|
|
|
|
|
// where it left off before the reconnect, so no need to reset in-progress files.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
std::map<std::wstring, fileInfo>::iterator curFile; |
|
|
|
|
|
|
|
for (curFile = fFileInfoMap.begin(); curFile != fFileInfoMap.end(); curFile++) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Reset files that were currently downloading
|
|
|
|
|
|
|
|
if (curFile->second.fDownloading) |
|
|
|
|
|
|
|
curFile->second.fDownloading = false; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (fNumDownloadRequestsRemaining > 0) { |
|
|
|
if (totalBytes && fProgress) |
|
|
|
|
|
|
|
{ |
|
|
|
LogMsg(kLogPerf, L"pfSecurePreloader: Auth reconnected, resetting in-progress file downloads"); |
|
|
|
fProgress->SetLength((hsScalar)totalBytes); |
|
|
|
|
|
|
|
fProgress->SetTitle("Downloading..."); |
|
|
|
// Issue some file download requests (up to kMaxConcurrency)
|
|
|
|
|
|
|
|
IIssueDownloadRequests(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
// This method uses only one manifest, so we're good to go now!
|
|
|
|
void pfSecurePreloader::IPreloadComplete () { |
|
|
|
PreloadNextFile(); |
|
|
|
DEL(fProgressBar); |
|
|
|
|
|
|
|
fProgressBar = nil; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
plPreloaderMsg * msg = TRACKED_NEW plPreloaderMsg(); |
|
|
|
|
|
|
|
msg->fSuccess = !fNetError; |
|
|
|
|
|
|
|
msg->Send(); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
void pfSecurePreloader::FilePreloaded(const wchar_t* file, hsStream* stream) |
|
|
|
hsBool pfSecurePreloader::MsgReceive (plMessage * msg) { |
|
|
|
{ |
|
|
|
|
|
|
|
// Clear out queue
|
|
|
|
if (plNetCommAuthConnectedMsg * authMsg = plNetCommAuthConnectedMsg::ConvertNoRef(msg)) { |
|
|
|
fDownloadEntries.pop(); |
|
|
|
|
|
|
|
const wchar_t* clientName = fManifestEntries.front(); // Stolen by plStreamSource
|
|
|
|
INotifyAuthReconnected(); |
|
|
|
fManifestEntries.pop(); |
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return hsKeyedObject::MsgReceive(msg); |
|
|
|
if (!fLegacyMode) // AuthSrv data caching is useless
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
plFileUtils::EnsureFilePathExists(clientName); |
|
|
|
|
|
|
|
SaveFile(stream, clientName); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
plSecureStream* ss = new plSecureStream(stream, fEncryptionKey); |
|
|
|
pfSecurePreloader * pfSecurePreloader::GetInstance () { |
|
|
|
plStreamSource::GetInstance()->InsertFile(clientName, ss); |
|
|
|
|
|
|
|
delete stream; // SecureStream holds its own decrypted buffer
|
|
|
|
|
|
|
|
|
|
|
|
if (!fInstance) { |
|
|
|
// Continue down the warpath
|
|
|
|
|
|
|
|
PreloadNextFile(); |
|
|
|
fInstance = NEWZERO(pfSecurePreloader); |
|
|
|
|
|
|
|
fInstance->RegisterAs(kSecurePreloader_KEY); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pfSecurePreloader* pfSecurePreloader::GetInstance() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (!fInstance) |
|
|
|
|
|
|
|
fInstance = new pfSecurePreloader; |
|
|
|
return fInstance;
|
|
|
|
return fInstance;
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
|
|
|
|
bool pfSecurePreloader::IsInstanced () { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return fInstance != nil; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
|
|
|
|
void pfSecurePreloader::Init () { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!fInitialized) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fInitialized = true; |
|
|
|
|
|
|
|
plgDispatch::Dispatch()->RegisterForExactType(plNetCommAuthConnectedMsg::Index(), GetKey()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
|
|
|
|
void pfSecurePreloader::Shutdown () { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (fInitialized) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fInitialized = false; |
|
|
|
|
|
|
|
plgDispatch::Dispatch()->UnRegisterForExactType(plNetCommAuthConnectedMsg::Index(), GetKey()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (fInstance) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fInstance->UnRegister(); |
|
|
|
|
|
|
|
fInstance = nil; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
|
|
|
|
pfSecurePreloader::pfSecurePreloader () { |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
|
|
|
|
pfSecurePreloader::~pfSecurePreloader () { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Cleanup(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|