Beispiel #1
0
        void downloadWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            DownloadProgress dp = e.UserState as DownloadProgress;
            int row             = -1;

            // Don't need to update the UI for transfers that are invisible
            if (!dp.visible)
            {
                return;
            }

            // Identify which row contains the download whose progress is being reported
            for (int i = 0; i < downloadGridView.RowCount; i++)
            {
                if ((((String)(downloadGridView["HashColumn", i].Value)).Equals(dp.hash)) &&
                    (((String)(downloadGridView["MacColumn", i].Value)).Equals(dp.mac)))
                {
                    row = i;
                    break;
                }
            }

            // This download is not yet shown in the UI
            if (row == -1 && downloadGridView.ColumnCount > 0)
            {
                String type    = dp.fileName.Substring(dp.fileName.LastIndexOf('.') + 1);
                Icon   zipIcon = null;

                try
                {
                    zipIcon = Icons.IconFromExtension(type);
                }
                catch (Exception e2)
                {
                }

                downloadGridView.Rows.Add(new object[] { zipIcon, dp.fileName, dp.status, e.ProgressPercentage + "%",
                                                         0, "Unknown", Utils.getHumanSize(dp.fileSize), dp.uploaderIP, "Cancel", Resources.remove_file_locked, dp.mac,
                                                         dp.hash, dp.fileSize, dp.downloadedFilePath, "false" });

                // To kick off UI update instantly
                uiUpdateTimer_Tick(sender, e);

                return;
            }

            downloadGridView["SpeedColumn", row].Value    = Utils.getHumanSpeed(dp.transferRate);
            downloadGridView["StatusColumn", row].Value   = dp.status;
            downloadGridView["ProgressColumn", row].Value = e.ProgressPercentage + "%";
            downloadGridView["PeerColumn", row].Value     = dp.nick;
            downloadGridView["FilePathColumn", row].Value = dp.downloadedFilePath;

            // Handles the case when a download is canceled, then restarted
            // It makes sure that the new download has a 'Cancel' button rather than a 'Clear' button
            if (!dp.status.Equals("Canceled") && downloadGridView["ActionColumn", row].Value.Equals("Clear")) // TODO: Finicky, change later
            {
                downloadGridView["ActionColumn", row].Value = "Cancel";
            }

            if (dp.isComplete)
            {
                downloadGridView["ActionColumn", row].Value    = "Open folder";
                downloadGridView["RemoveColumn", row].Value    = Resources.remove_file;
                downloadGridView["RemovableColumn", row].Value = "true";
                notifyIcon.BalloonTipIcon  = ToolTipIcon.Info;
                notifyIcon.BalloonTipTitle = "Download complete   ";
                notifyIcon.BalloonTipText  = (String)downloadGridView["FileNameColumn", row].Value;
                notifyIcon.ShowBalloonTip(5000);
            }

            if (dp.isFailedUnrecoverably)
            {
                downloadGridView["RemoveColumn", row].Value    = Resources.remove_file;
                downloadGridView["RemovableColumn", row].Value = "true";
                notifyIcon.BalloonTipIcon  = ToolTipIcon.Error;
                notifyIcon.BalloonTipTitle = "Download failed   ";
                notifyIcon.BalloonTipText  = (String)downloadGridView["FileNameColumn", row].Value;
                notifyIcon.ShowBalloonTip(5000);
            }

            double secondsToComplete = ((dp.fileSize - dp.bytesDownloaded) / 1024.0) / dp.averageTransferRate;

            if (secondsToComplete > 0)
            {
                downloadGridView["ETAColumn", row].Value = Utils.getHumanTime(secondsToComplete);
            }
            else
            {
                downloadGridView["ETAColumn", row].Value = "";
            }
        }
Beispiel #2
0
        public static string postDownload(DownloadProgress dp, PendingResponse pr, BackgroundWorker worker)
        {
            int percentComplete = (int)(100 * dp.bytesDownloaded / pr.fileSize);

            if (dp.isFailed)
            {
                dp.attempts = dp.attempts + 1;
                if (dp.attempts > 10)
                {
                    dp.status = "Failed";
                    dp.isFailedUnrecoverably = true;
                    worker.ReportProgress(percentComplete, dp);
                    return(null);
                }

                dp.status   = "Retrying.. (" + dp.attempts + ")";
                dp.isFailed = false;
                worker.ReportProgress(percentComplete, dp);

                System.Threading.Thread.Sleep(3000);

                return("FAILED");
            }

            BackgroundWorker updateWorker = new BackgroundWorker();

            updateWorker.DoWork             += Downloads.updateWorker_DoWork;
            updateWorker.RunWorkerCompleted += Downloads.updateWorker_RunWorkerCompleted;

            // Set update parameters
            UpdateRequest updateRequest = new UpdateRequest();

            updateRequest.transferID = dp.transferID;
            updateRequest.uploader   = dp.mac;

            if (dp.isCanceled)
            {
                try
                { File.Delete(dp.downloadedFilePath); }
                catch (Exception e2)
                { } // Do nothing. We only want to try and delete the file.

                // Remove from pendingToDownload
                DownloadProgress temp = null;
                pendingToDownload.TryRemove(pr, out temp);

                updateRequest.newHash = dp.hash;
                updateRequest.status  = "canceled";

                updateWorker.RunWorkerAsync(updateRequest);
                return(null);
            }

            // Download neither canceled nor failed

            String newHash = Indexer.GenerateHash(dp.downloadedFilePath);

            if (dp.type == "secondleg" || dp.type == "direct")
            {
                if (newHash == dp.hash)
                {
                    Utils.writeLog("download: Hash verified");
                    dp.isComplete = true;
                    dp.status     = "Completed";
                    worker.ReportProgress(100, dp);

                    // Removing from partially-downloaded-files list
                    Settings.Default.partiallyDownloadedFiles.Replace(dp.downloadedFilePath + "; ", "");
                }
                else
                {
                    Utils.writeLog("download: Hash verification failed");
                    dp.status                = "Failed integrity check";
                    dp.isHashMismatch        = true;
                    dp.isFailed              = true;
                    dp.isFailedUnrecoverably = true;
                    worker.ReportProgress(100, dp);

                    try
                    { File.Delete(dp.downloadedFilePath); }
                    catch (Exception e2)
                    { } // Do nothing. We only want to try and delete the file.
                }

                updateRequest.newHash = newHash;
                updateRequest.status  = "done";

                updateWorker.RunWorkerAsync(updateRequest);

                return(newHash);
            }

            if (dp.type == "firstleg")
            {
                // Rename the file to the new hash

                String newPath = dp.downloadedFilePath.Substring(0, dp.downloadedFilePath.LastIndexOf(@"\"));
                newPath = newPath + "\\" + newHash + ".bounced";

                // Removing from partially-downloaded-files list
                Settings.Default.partiallyDownloadedFiles.Replace(dp.downloadedFilePath + "; ", "");

                try
                {
                    File.Move(dp.downloadedFilePath, newPath);
                }
                catch (Exception e)
                {
                    Utils.writeLog("download: Critical. Unable to rename file to the new hash.");
                }

                dp.status     = "Completed";
                dp.isComplete = true;
                worker.ReportProgress(100, dp);
            }

            updateRequest.newHash = newHash;
            updateRequest.status  = "done";

            updateWorker.RunWorkerAsync(updateRequest);

            return(newHash);
        }
Beispiel #3
0
        private void pollPendingWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            List <PendingResponse> latestPending = (List <PendingResponse>)e.Result;

            if (latestPending == null)
            {
                statusPictureBox.Image = Resources.connection_working;
                mainToolTip.SetToolTip(statusPictureBox, "Trying to connect..");
                statusLabel.Text         = "Lost connection to network";
                pollPendingTimer.Enabled = false;
                reconnectTimer.Enabled   = true;
                Utils.writeLog("pollPendingWorker_RunWorkerCompleted: Received null response from server");
                return;
            }

            foreach (PendingResponse pr in latestPending)
            {
                if (pr == null || pr.type == null)
                {
                    Utils.writeLog("pollPendingWorker_RunWorkerCompleted: Received a null pending");
                    continue;
                }
                if (pr.type.Equals("delete"))
                {
                    Utils.writeLog("pollPendingWorker_RunWorkerCompleted: Got delete request for " + pr.fileHash + " (" + pr.fileName + ") ");
                    String filePath = Utils.getAppDataPath(@"\Bounces\" + pr.fileHash + ".bounced");
                    try
                    {
                        File.Delete(filePath);
                    }
                    catch (Exception e2)
                    {
                        //TODO: Do nothing.
                    }

                    // Tell the server we have deleted the file
                    BackgroundWorker updateWorker = new BackgroundWorker();
                    updateWorker.DoWork             += Downloads.updateWorker_DoWork;
                    updateWorker.RunWorkerCompleted += Downloads.updateWorker_RunWorkerCompleted;

                    // Set update parameters and kick off update
                    UpdateRequest ur = new UpdateRequest();
                    ur.transferID = pr.transferID;
                    ur.status     = "done";
                    ur.uploader   = pr.uploader;
                    updateWorker.RunWorkerAsync(ur);

                    continue;
                }

                bool performPending = false;

                // Checking if the same file is already being downloaded by the client
                if (!Downloads.pendingToDownload.ContainsKey(pr))
                {
                    foreach (PendingResponse existingPending in Downloads.pendingToDownload.Keys)
                    {
                        if (existingPending.fileHash.Equals(pr.fileHash))
                        {
                            return;
                        }
                    }
                    performPending = true;
                }

                if (performPending)
                {
                    Utils.writeLog("Added " + pr.fileName + " to download queue");
                    DownloadProgress dip = new DownloadProgress(pr);
                    Downloads.pendingToDownload[pr] = dip;

                    BackgroundWorker downloadWorker = new BackgroundWorker();
                    downloadWorker.WorkerReportsProgress      = true;
                    downloadWorker.WorkerSupportsCancellation = true;
                    downloadWorker.DoWork             += downloadWorker_DoWork;
                    downloadWorker.ProgressChanged    += downloadWorker_ProgressChanged;
                    downloadWorker.RunWorkerCompleted += downloadWorker_RunWorkerCompleted;

                    // This is what is sent to the backgroundworker
                    Tuple <PendingResponse, DownloadProgress> downloadArgs =
                        new Tuple <PendingResponse, DownloadProgress>(pr, dip);

                    downloadWorker.RunWorkerAsync(downloadArgs);
                }
            }
        }
Beispiel #4
0
        public static string download(BackgroundWorker worker, PendingResponse pr, DownloadProgress dp, long startByte)
        {
            TcpClient     tcpClient    = new TcpClient();
            NetworkStream clientStream = null;

            try
            {
                tcpClient.Connect(pr.uploaderIP, 8002);

                clientStream = tcpClient.GetStream();
                Utils.writeLog("download: Sending download instruction to peer " + pr.uploaderIP + "...");

                //Format: fileHash | transfer ID | transfer-type
                Utils.writeLog("tid is " + pr.transferID);
                ASCIIEncoding encoder = new ASCIIEncoding();
                byte[]        buffer  = encoder.GetBytes(pr.fileHash + "|" + pr.transferID + "|" + pr.type + "|" + startByte);

                clientStream.Write(buffer, 0, buffer.Length);
                clientStream.Flush();
                Utils.writeLog("download: Download started.");
            }
            catch (Exception e)
            {
                Utils.writeLog("download: Could not establish connection. Error : " + e);
                dp.isFailed = true;
                return(postDownload(dp, pr, worker));
            }

            // Begin file transfer
            FileStream strLocal = null;

            Downloads.currentDownloads.Add(dp);

            // Add the download to the gridview
            worker.ReportProgress(0, dp);

            #region initvars

            long bytesDownloaded = startByte; //Total bytes downloaded for the file
            int  bytesSize;                   //Number of bytes read by the stream reader
            int  tempTransferRate  = 0;       //Instantaneous (for 1 refresh cycle) download rate
            long downloadedInCycle = 0;       //Total bytes downloaded in the last refresh cycle
            int  percentComplete   = 0;

            DateTime startTime = DateTime.Now;  //To track total download time
            DateTime refresh   = DateTime.Now;  //To track time since last refresh

            byte[] downBuffer = new byte[4096];

            bool appendToExistingFile = false;

            // Find a free filename

            if (File.Exists(dp.downloadedFilePath))
            {
                long existingFileLength = new FileInfo(dp.downloadedFilePath).Length;

                // First file found should be appended to
                if (startByte > 0 && startByte == existingFileLength)
                {
                    appendToExistingFile = true;
                }
                else
                {
                    String candidatePath = "";
                    for (int i = 2; i < 100; i++) // 100 here is arbitrary, just want to make sure it doesnt loop forever
                    {
                        candidatePath  = dp.downloadedFilePath.Substring(0, dp.downloadedFilePath.LastIndexOf('.'));
                        candidatePath += " (" + i + ")";
                        candidatePath += dp.downloadedFilePath.Substring(dp.downloadedFilePath.LastIndexOf('.'));

                        if (!File.Exists(candidatePath))
                        {
                            Utils.writeLog("download: Found free file path " + candidatePath);
                            dp.downloadedFilePath = candidatePath;
                            dp.fileName           = dp.downloadedFilePath.Substring(dp.downloadedFilePath.LastIndexOf(@"\") + 1);
                            break;
                        }
                        else
                        {
                            existingFileLength = new FileInfo(candidatePath).Length;
                            if (startByte > 0 && startByte == existingFileLength)
                            {
                                dp.downloadedFilePath = candidatePath;
                                appendToExistingFile  = true;
                                break;
                            }
                        }
                    }
                }
            }

            try
            {
                if (appendToExistingFile)
                {
                    strLocal = new FileStream(dp.downloadedFilePath,
                                              FileMode.Append, FileAccess.Write, FileShare.ReadWrite);
                }
                else
                {
                    strLocal = new FileStream(dp.downloadedFilePath,
                                              FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
                }
            }
            catch (Exception e)
            {
                Utils.writeLog("download: Error creating file : " + e);
                // Attempt to recover from error that download folder doesn't exist.
                String filePath   = dp.downloadedFilePath;
                String folderPath = filePath.Substring(0, filePath.LastIndexOf("\\"));
                try
                {
                    System.IO.Directory.CreateDirectory(folderPath);
                    strLocal = new FileStream(dp.downloadedFilePath,
                                              FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
                }
                catch (Exception e2)
                {
                    Utils.writeLog("download: Unrecoverable error while creating folder to hold file");
                    MessageBox.Show("Could not download file as the download folder could not be found or created",
                                    "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return(null);
                }
            }

            Settings.Default.partiallyDownloadedFiles = dp.downloadedFilePath + "; " +
                                                        Settings.Default.partiallyDownloadedFiles;

            #endregion

            try
            {
                // Perform file transfer.
                clientStream.ReadTimeout = 6000; // Need to timeout now to prevent stalled appearance in UI

                while ((bytesSize = clientStream.Read(downBuffer, 0, downBuffer.Length)) > 0)
                {
                    // In case user cancels download
                    if (pendingToDownload[pr] == null || worker.CancellationPending)
                    {
                        throw new DownloadCanceledException("Download canceled");
                    }

                    downloadedInCycle += bytesSize;
                    bytesDownloaded    = bytesDownloaded + bytesSize;
                    dp.bytesDownloaded = bytesDownloaded;
                    strLocal.Write(downBuffer, 0, bytesSize);

                    if (pr.fileSize != 0)
                    {
                        percentComplete = (int)(100 * bytesDownloaded / pr.fileSize);
                    }

                    // Report progress to UI at intervals
                    double msElapsedSinceRefresh = (DateTime.Now - refresh).TotalMilliseconds;
                    if (msElapsedSinceRefresh > 1000)
                    {
                        tempTransferRate = (int)((downloadedInCycle / 1024.0) / (DateTime.Now - refresh).TotalSeconds);

                        dp.status = "Downloading";

                        // Initialize download speed
                        if (dp.averageTransferRate == 0)
                        {
                            dp.averageTransferRate = tempTransferRate;
                        }

                        // Compute download speed with smoothing factor
                        dp.transferRate        = tempTransferRate;
                        dp.averageTransferRate = (0.01) * tempTransferRate + (0.99) * dp.averageTransferRate;

                        worker.ReportProgress(percentComplete, dp);

                        refresh           = DateTime.Now;
                        downloadedInCycle = 0;
                    }
                }

                dp.bytesDownloaded = bytesDownloaded;
                dp.transferRate    = tempTransferRate;
                worker.ReportProgress(100, dp);

                Utils.writeLog("download: Completed download of " + pr.fileName +
                               " (" + dp.fileSize + ") Type:" + dp.type);
                dp.status = "Checking file..";
            }
            catch (DownloadCanceledException dce) // Occurs when user cancels
            {
                Utils.writeLog("download: Canceled by user");
                dp.status     = "Canceled";
                dp.isCanceled = true;
            }
            catch (Exception e) // Should only occur due to poor network/peer going offline
            {
                Utils.writeLog("download: Error:" + e.ToString());
                dp.status   = "Failed";
                dp.isFailed = true;
            }
            finally
            {
                worker.ReportProgress(percentComplete, dp);
                strLocal.Close();
                clientStream.Close();
            }

            return(postDownload(dp, pr, worker));
        }