static void ManifestDownloaded( ENetError result, void* param, const wchar_t group[], const NetCliFileManifestEntry manifest[], uint32_t entryCount) { plResPatcher* patcher = (plResPatcher*)param; char* name = hsWStringToString(group); if (IS_NET_SUCCESS(result)) PatcherLog(kInfo, " Downloaded manifest %s", name); else { PatcherLog(kError, " Failed to download manifest %s", name); patcher->Finish(false); delete[] name; return; } for (uint32_t i = 0; i < entryCount; ++i) { const NetCliFileManifestEntry mfs = manifest[i]; char* fileName = hsWStringToString(mfs.clientName); // See if the files are the same // 1. Check file size before we do time consuming md5 operations // 2. Do wasteful md5. We should consider implementing a CRC instead. if (plFileUtils::GetFileSize(fileName) == mfs.fileSize) { plMD5Checksum cliMD5(fileName); plMD5Checksum srvMD5; char* eapSucksString = hsWStringToString(mfs.md5); srvMD5.SetFromHexString(eapSucksString); delete[] eapSucksString; if (cliMD5 == srvMD5) { delete[] fileName; continue; } else PatcherLog(kInfo, " Enqueueing %s: MD5 Checksums Differ", fileName); } else PatcherLog(kInfo, " Enqueueing %s: File Sizes Differ", fileName); // If we're still here, then we need to update the file. float size = mfs.zipSize ? (float)mfs.zipSize : (float)mfs.fileSize; patcher->GetProgress()->SetLength(size + patcher->GetProgress()->GetMax()); patcher->RequestFile(mfs.downloadName, mfs.clientName); } patcher->IssueRequest(); delete[] name; }
static void FileDownloaded( ENetError result, void* param, const plFileName & filename, hsStream* writer) { plResPatcher* patcher = (plResPatcher*)param; plFileName file = filename; if (((plResDownloadStream*)writer)->IsZipped()) file = file.StripFileExt(); // Kill off .gz writer->Close(); switch (result) { case kNetSuccess: { PatcherLog(kStatus, " Download Complete: %s", file.AsString().c_str()); // If this is a PRP, then we need to add it to the ResManager plFileName clientPath = static_cast<plResDownloadStream*>(writer)->GetFileName(); if (clientPath.GetFileExt().CompareI("prp") == 0) { plResManager* clientResMgr = static_cast<plResManager*>(hsgResMgr::ResMgr()); clientResMgr->AddSinglePage(clientPath); } // Continue down the warpath patcher->IssueRequest(); delete writer; return; } case kNetErrFileNotFound: PatcherLog(kError, " Download Failed: %s not found", file.AsString().c_str()); break; default: char* error = hsWStringToString(NetErrorToString(result)); PatcherLog(kError, " Download Failed: %s", error); delete[] error; break; } // Failure case static_cast<plResDownloadStream*>(writer)->Unlink(); patcher->Finish(false); delete writer; }
void plResPatcher::Start() { hsAssert(!fPatching, "Too many calls to plResPatcher::Start"); fPatching = true; PatcherLog(kHeader, "--- Patch Started (%i requests) ---", fRequests.size()); fProgress = plProgressMgr::GetInstance()->RegisterOperation(0.0, "Checking for updates...", plProgressMgr::kUpdateText, false, true); IssueRequest(); }
void plResPatcher::IssueRequest() { if (!fPatching) return; if (fRequests.empty()) // Wheee! Finish(); else { Request req = fRequests.front(); fRequests.pop(); std::wstring title; if (req.fType == kManifest) { char* eapSucksString = hsWStringToString(req.fFile.c_str()); PatcherLog(kMajorStatus, " Downloading manifest... %s", eapSucksString); xtl::format(title, L"Checking %s for updates...", req.fFile.c_str()); NetCliFileManifestRequest(ManifestDownloaded, this, req.fFile.c_str()); delete[] eapSucksString; } else if (req.fType == kFile) { char* eapSucksString = hsWStringToString(req.fFriendlyName.c_str()); PatcherLog(kMajorStatus, " Downloading file... %s", eapSucksString); xtl::format(title, L"Downloading... %s", plFileUtils::GetFileName(req.fFriendlyName.c_str())); // If this is a PRP, we need to unload it from the ResManager if (stricmp(plFileUtils::GetFileExt(eapSucksString), "prp") == 0) ((plResManager*)hsgResMgr::ResMgr())->RemoveSinglePage(eapSucksString); plFileUtils::EnsureFilePathExists(req.fFriendlyName.c_str()); plResDownloadStream* stream = new plResDownloadStream(fProgress, req.fFile.c_str()); if(stream->Open(eapSucksString, "wb")) NetCliFileDownloadRequest(req.fFile.c_str(), stream, FileDownloaded, this); else { PatcherLog(kError, " Unable to create file %s", eapSucksString); Finish(false); } delete[] eapSucksString; } char* hack = hsWStringToString(title.c_str()); fProgress->SetTitle(hack); delete[] hack; } }
static void FileDownloaded( ENetError result, void* param, const wchar_t filename[], hsStream* writer) { plResPatcher* patcher = (plResPatcher*)param; char* name = hsWStringToString(filename); if (((plResDownloadStream*)writer)->IsZipped()) plFileUtils::StripExt(name); // Kill off .gz writer->Close(); switch (result) { case kNetSuccess: PatcherLog(kStatus, " Download Complete: %s", name); // If this is a PRP, then we need to add it to the ResManager if (stricmp(plFileUtils::GetFileExt(name), "prp") == 0) ((plResManager*)hsgResMgr::ResMgr())->AddSinglePage(name); // Continue down the warpath patcher->IssueRequest(); delete[] name; delete writer; return; case kNetErrFileNotFound: PatcherLog(kError, " Download Failed: %s not found", name); break; default: char* error = hsWStringToString(NetErrorToString(result)); PatcherLog(kError, " Download Failed: %s", error); delete[] error; break; } // Failure case ((plResDownloadStream*)writer)->Unlink(); patcher->Finish(false); delete[] name; delete writer; }
void plResPatcher::Finish(bool success) { while (fRequests.size()) fRequests.pop(); fPatching = false; if (success) PatcherLog(kHeader, "--- Patch Completed Successfully ---"); else { PatcherLog(kHeader, "--- Patch Killed by Error ---"); if (fProgress) fProgress->SetAborting(); } delete fProgress; fProgress = nil; plResPatcherMsg* pMsg = new plResPatcherMsg(success, sLastError); delete[] sLastError; sLastError = nil; pMsg->Send(); // whoosh... off it goes }
void plResPatcher::IssueRequest() { if (!fPatching) return; if (fRequests.empty()) // Wheee! Finish(); else { Request req = fRequests.front(); fRequests.pop(); plString title; if (req.fType == kManifest) { PatcherLog(kMajorStatus, " Downloading manifest... %s", req.fFile.AsString().c_str()); title = plString::Format("Checking %s for updates...", req.fFile.AsString().c_str()); NetCliFileManifestRequest(ManifestDownloaded, this, req.fFile.AsString().ToWchar()); } else if (req.fType == kFile) { PatcherLog(kMajorStatus, " Downloading file... %s", req.fFriendlyName.AsString().c_str()); title = plString::Format("Downloading... %s", req.fFriendlyName.GetFileName().c_str()); // If this is a PRP, we need to unload it from the ResManager if (req.fFriendlyName.GetFileExt().CompareI("prp") == 0) ((plResManager*)hsgResMgr::ResMgr())->RemoveSinglePage(req.fFriendlyName); plFileSystem::CreateDir(req.fFriendlyName.StripFileName(), true); plResDownloadStream* stream = new plResDownloadStream(fProgress, req.fFile); if (stream->Open(req.fFriendlyName, "wb")) NetCliFileDownloadRequest(req.fFile, stream, FileDownloaded, this); else { PatcherLog(kError, " Unable to create file %s", req.fFriendlyName.AsString().c_str()); Finish(false); } } fProgress->SetTitle(title.c_str()); } }