示例#1
0
void pfPatcherWorker::ProcessFile()
{
    do {
        NetCliFileManifestEntry& entry = fQueuedFiles.front();

        // eap sucks
        plFileName clName = plString::FromWchar(entry.clientName);
        plString dlName = plString::FromWchar(entry.downloadName);

        // Check to see if ours matches
        plFileInfo mine(clName);
        if (mine.FileSize() == entry.fileSize) {
            plMD5Checksum cliMD5(clName);
            plMD5Checksum srvMD5;
            srvMD5.SetFromHexString(plString::FromWchar(entry.md5, 32).c_str());

            if (cliMD5 == srvMD5) {
                WhitelistFile(clName, false);
                fQueuedFiles.pop_front();
                continue;
            }
        }

        // It's different... but do we want it?
        if (fFileDownloadDesired) {
            if (!fFileDownloadDesired(clName)) {
                PatcherLogRed("\tDeclined '%S'", entry.clientName);
                fQueuedFiles.pop_front();
                continue;
            }
        }

        // If you got here, they're different and we want it.
        PatcherLogYellow("\tEnqueuing '%S'", entry.clientName);
        plFileSystem::CreateDir(plFileName(clName).StripFileName());

        // If someone registered for SelfPatch notifications, then we should probably
        // let them handle the gruntwork... Otherwise, go nuts!
        if (fSelfPatch) {
            if (clName == plFileSystem::GetCurrentAppPath().GetFileName()) {
                clName += ".tmp"; // don't overwrite myself!
                entry.flags |= kSelfPatch;
            }
        }

        pfPatcherStream* s = new pfPatcherStream(this, dlName, entry);
        s->Open(clName, "wb");

        hsTempMutexLock lock(fRequestMut);
        fRequests.push_back(Request(dlName, Request::kFile, s));
        fQueuedFiles.pop_front();

        if (!fRequestActive)
            IssueRequest();
    } while (!fQueuedFiles.empty());
}
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;
}