// Update downloaded flag for this file void CResourceManager::OnDownloadedResourceFile( const SString& strInFilename ) { SString strFilename = PathConform( strInFilename ).ToLower(); CDownloadableResource* pResourceFile = MapFindRef( m_ResourceFileMap, strFilename ); if ( pResourceFile ) pResourceFile->SetDownloaded(); }
/////////////////////////////////////////////////////////////// // // CResourceFileDownloadManager::DownloadFinished // // Callback when file download has finished // /////////////////////////////////////////////////////////////// void CResourceFileDownloadManager::DownloadFinished(const SHttpDownloadResult& result) { CDownloadableResource* pResourceFile = ResolveDownloadContextString((SString*)result.pObj); if (!pResourceFile) return; assert(ListContains(m_ActiveFileDownloadList, pResourceFile)); if (result.bSuccess) { CChecksum checksum = CChecksum::GenerateChecksumFromFile(pResourceFile->GetName()); if (checksum != pResourceFile->GetServerChecksum()) { // Checksum failed - Try download on next server if (BeginResourceFileDownload(pResourceFile, pResourceFile->GetHttpServerIndex() + 1)) { // Was re-added - Add size again to total. AddDownloadSize(pResourceFile->GetDownloadSize()); SString strMessage("External HTTP file mismatch (Retrying this file with internal HTTP) [%s]", *ConformResourcePath(pResourceFile->GetName())); g_pClientGame->TellServerSomethingImportant(1011, strMessage, 3); return; } } } else { // Download failed due to connection type problem CNetHTTPDownloadManagerInterface* pHTTP = g_pNet->GetHTTPDownloadManager(m_HttpServerList[pResourceFile->GetHttpServerIndex()].downloadChannel); SString strHTTPError = pHTTP->GetError(); // Disable server from being used (if possible) if (DisableHttpServer(pResourceFile->GetHttpServerIndex())) { // Try download on next server if (BeginResourceFileDownload(pResourceFile, pResourceFile->GetHttpServerIndex() + 1)) { // Was re-added - Add size again to total. AddDownloadSize(pResourceFile->GetDownloadSize()); SString strMessage("External HTTP file download error:[%d] %s (Disabling External HTTP) [%s]", result.iErrorCode, *strHTTPError, *ConformResourcePath(pResourceFile->GetName())); g_pClientGame->TellServerSomethingImportant(1012, strMessage, 3); return; } } m_strLastHTTPError = strHTTPError; } // File now done (or failed) ListRemove(m_ActiveFileDownloadList, pResourceFile); pResourceFile->SetIsWaitingForDownload(false); }
// Check resource file data matches server checksum void CResourceManager::ValidateResourceFile( const SString& strInFilename, const CBuffer& fileData ) { SString strFilename = PathConform( strInFilename ).ToLower(); CDownloadableResource* pResourceFile = MapFindRef( m_ResourceFileMap, strFilename ); if ( pResourceFile ) { if ( pResourceFile->IsAutoDownload() && !pResourceFile->IsDownloaded() ) { // Scripting error g_pClientGame->GetScriptDebugging()->LogError( NULL, "Attempt to load '%s' before onClientFileDownloadComplete event", *ConformResourcePath( strInFilename ) ); } else { CChecksum checksum; if ( !fileData.IsEmpty() ) checksum = CChecksum::GenerateChecksumFromBuffer( fileData.GetData(), fileData.GetSize() ); else checksum = CChecksum::GenerateChecksumFromFile( strInFilename ); if ( checksum != pResourceFile->GetServerChecksum() ) { if ( pResourceFile->IsDownloaded() ) { char szMd5[33]; CMD5Hasher::ConvertToHex( checksum.md5, szMd5 ); char szMd5Wanted[33]; CMD5Hasher::ConvertToHex( pResourceFile->GetServerChecksum().md5, szMd5Wanted ); SString strMessage( "Resource file checksum failed: %s [Size:%d MD5:%s][Wanted:%s][datasize:%d] ", *ConformResourcePath( strInFilename ), (int)FileSize( strInFilename ), szMd5, szMd5Wanted, fileData.GetSize() ); g_pClientGame->TellServerSomethingImportant( 1007, strMessage, false ); g_pCore->GetConsole ()->Print( strMessage ); AddReportLog( 7057, strMessage + g_pNet->GetConnectedServer( true ), 10 ); } else if ( !pResourceFile->IsAutoDownload() ) { char szMd5[33]; CMD5Hasher::ConvertToHex( checksum.md5, szMd5 ); SString strMessage( "Attempt to load resource file before it is ready: %s [Size:%d MD5:%s] ", *ConformResourcePath( strInFilename ), (int)FileSize( strInFilename ), szMd5 ); g_pClientGame->TellServerSomethingImportant( 1008, strMessage, false ); g_pCore->GetConsole ()->Print( strMessage ); AddReportLog( 7058, strMessage + g_pNet->GetConnectedServer( true ), 10 ); } } } } }
void CDownloadMgr::Init( const char *pInResourceDescriptionsFile) { m_resources.clear(); XmlNodeRef node=GetISystem()->LoadXmlFromFile(pInResourceDescriptionsFile); if (!node || strcmp("downloadmgr_config",node->getTag())) { GameWarning("Failed to load download mgr config file %s", pInResourceDescriptionsFile); return; } CDownloadableResource defaultResource; XmlNodeRef defaultXML(0); #ifdef GAME_IS_CRYSIS2 for (int i=0, n=node->getChildCount(); i<n; i++) { XmlNodeRef x=node->getChild(i); if (x && strcmp(x->getTag(),"default_resource")==0) { const char *config=NULL; if (x->getAttr("config",&config) && strcmp(config,g_pGameCVars->g_dataCentreConfig)==0) { defaultXML=x; break; } } } #endif if (defaultXML) { defaultResource.LoadConfig(defaultXML); } XmlNodeRef resources=node->findChild("resources"); if (resources) { int numResources=resources->getChildCount(); m_resources.reserve(numResources+k_localizedResourceSlop); for (int i=0; i<numResources; ++i) { bool ok=false; CDownloadableResourcePtr pParse=new CDownloadableResource(defaultResource); if (pParse) { pParse->LoadConfig(resources->getChild(i)); ok=pParse->Validate(); } if (!ok) { GameWarning("Error loading resource description %d %s from %s",i,pParse->m_descName.c_str(),pInResourceDescriptionsFile); } else { m_resources.push_back(pParse); } } } }