/* Download Manager */ #include "updater/download_curl.sp" #include "updater/download_socket.sp" #include "updater/download_steamtools.sp" #include "updater/download_steamworks.sp" DataPackPos QueuePack_URL; void FinalizeDownload(int index) { /* Strip the temporary file extension from downloaded files. */ char newpath[PLATFORM_MAX_PATH]; char oldpath[PLATFORM_MAX_PATH]; Handle hFiles = Updater_GetFiles(index); int maxFiles = GetArraySize(hFiles); for (int i = 0; i < maxFiles; i++) { GetArrayString(hFiles, i, newpath, sizeof(newpath)); Format(oldpath, sizeof(oldpath), "%s.%s", newpath, TEMP_FILE_EXT); // Rename doesn't overwrite on Windows. Make sure the path is clear. if (FileExists(newpath)) { DeleteFile(newpath); } RenameFile(newpath, oldpath); } ClearArray(hFiles); } void AbortDownload(int index) { /* Delete all downloaded temporary files. */ char path[PLATFORM_MAX_PATH]; Handle hFiles = Updater_GetFiles(index); int maxFiles = GetArraySize(hFiles); for (int i = 0; i < maxFiles; i++) { GetArrayString(hFiles, 0, path, sizeof(path)); Format(path, sizeof(path), "%s.%s", path, TEMP_FILE_EXT); if (FileExists(path)) { DeleteFile(path); } } ClearArray(hFiles); } void ProcessDownloadQueue(bool force=false) { if (!force && (g_bDownloading || !GetArraySize(g_hDownloadQueue))) { return; } Handle hQueuePack = GetArrayCell(g_hDownloadQueue, 0); SetPackPosition(hQueuePack, QueuePack_URL); char url[MAX_URL_LENGTH]; char dest[PLATFORM_MAX_PATH]; ReadPackString(hQueuePack, url, sizeof(url)); ReadPackString(hQueuePack, dest, sizeof(dest)); if (!CURL_AVAILABLE() && !SOCKET_AVAILABLE() && !STEAMTOOLS_AVAILABLE() && !STEAMWORKS_AVAILABLE()) { SetFailState(EXTENSION_ERROR); } #if defined DEBUG Updater_DebugLog("Download started:"); Updater_DebugLog(" [0] URL: %s", url); Updater_DebugLog(" [1] Destination: %s", dest); #endif g_bDownloading = true; if (STEAMWORKS_AVAILABLE()) { if (SteamWorks_IsLoaded()) { Download_SteamWorks(url, dest); } else { CreateTimer(10.0, Timer_RetryQueue); } } else if (STEAMTOOLS_AVAILABLE()) { if (g_bSteamLoaded) { Download_SteamTools(url, dest); } else { CreateTimer(10.0, Timer_RetryQueue); } } else if (CURL_AVAILABLE()) { Download_cURL(url, dest); } else if (SOCKET_AVAILABLE()) { Download_Socket(url, dest); } } public Action Timer_RetryQueue(Handle timer) { ProcessDownloadQueue(true); return Plugin_Stop; } void AddToDownloadQueue(int index, const char[] url, const char[] dest) { Handle hQueuePack = CreateDataPack(); WritePackCell(hQueuePack, index); QueuePack_URL = GetPackPosition(hQueuePack); WritePackString(hQueuePack, url); WritePackString(hQueuePack, dest); PushArrayCell(g_hDownloadQueue, hQueuePack); ProcessDownloadQueue(); } void DownloadEnded(bool successful, const char[] error="") { Handle hQueuePack = GetArrayCell(g_hDownloadQueue, 0); ResetPack(hQueuePack); char url[MAX_URL_LENGTH]; char dest[PLATFORM_MAX_PATH]; int index = ReadPackCell(hQueuePack); ReadPackString(hQueuePack, url, sizeof(url)); ReadPackString(hQueuePack, dest, sizeof(dest)); // Remove from the queue. CloseHandle(hQueuePack); RemoveFromArray(g_hDownloadQueue, 0); #if defined DEBUG Updater_DebugLog(" [2] Successful: %s", successful ? "Yes" : "No"); #endif switch (Updater_GetStatus(index)) { case Status_Checking: { if (!successful || !ParseUpdateFile(index, dest)) { Updater_SetStatus(index, Status_Idle); #if defined DEBUG if (error[0] != '\0') { Updater_DebugLog(" [2] %s", error); } #endif } } case Status_Downloading: { if (successful) { // Check if this was the last file we needed. char lastfile[PLATFORM_MAX_PATH]; Handle hFiles = Updater_GetFiles(index); GetArrayString(hFiles, GetArraySize(hFiles) - 1, lastfile, sizeof(lastfile)); Format(lastfile, sizeof(lastfile), "%s.%s", lastfile, TEMP_FILE_EXT); if (StrEqual(dest, lastfile)) { Handle hPlugin = IndexToPlugin(index); Fwd_OnPluginUpdating(hPlugin); FinalizeDownload(index); char sName[64]; if (!GetPluginInfo(hPlugin, PlInfo_Name, sName, sizeof(sName))) { strcopy(sName, sizeof(sName), "Null"); } Updater_Log("Successfully updated and installed \"%s\".", sName); Updater_SetStatus(index, Status_Updated); Fwd_OnPluginUpdated(hPlugin); } } else { // Failed during an update. AbortDownload(index); Updater_SetStatus(index, Status_Error); char filename[64]; GetPluginFilename(IndexToPlugin(index), filename, sizeof(filename)); Updater_Log("Error downloading update for plugin: %s", filename); Updater_Log(" [0] URL: %s", url); Updater_Log(" [1] Destination: %s", dest); if (error[0] != '\0') { Updater_Log(" [2] %s", error); } } } case Status_Error: { // Delete any additional files that this plugin had queued. if (successful && FileExists(dest)) { DeleteFile(dest); } } } g_bDownloading = false; ProcessDownloadQueue(); }