/// <summary>Returns the first new message that satisfies the given condition within /// a timeout period in seconds, or null if no match is received.</summary> public async Task <SocketUserMessage> GetResponseAsync(Func <SocketUserMessage, bool> condition, int timeout = 30) { var pending = new PendingResponse(condition); pendingResponses.TryAdd(pending, 0); try { await Task.Delay(timeout * 1000, pending.Token); } catch (OperationCanceledException) { } finally { pendingResponses.TryRemove(pending); } return(pending.Response); }
public Watch CreateWatch(DiscoveryRequest request) { var info = _nodeInfos.GetOrAdd(request.Node.Id, id => new NodeInfo()); IDictionary <string, IMessage> resources; lock (info.Lock) { if (info.Snapshot == null || request.VersionInfo == info.Snapshot.GetVersion(request.TypeUrl) || request.ErrorDetail != null) { var watchId = Interlocked.Increment(ref _watchId); var pendingResponse = new PendingResponse(request); info.PendingResponses[watchId] = pendingResponse; _logger.DebugF($"Returning pending response TypeUrl: {request.TypeUrl}, Version: {request.VersionInfo}, Nonce: {request.ResponseNonce}"); return(new Watch( pendingResponse.Response, () => CancelWatch(pendingResponse.Request.Node.Id, watchId))); } resources = info.Snapshot.GetResources(request.TypeUrl); } var response = CreateStreamResponse(request, resources, info.Snapshot.GetVersion(request.TypeUrl)); if (response == null) { // Incomplete request in ADS mode. Do not respond. return(Watch.Empty); } _logger.DebugF($"-> Returning immediate response TypeUrl: {response.TypeUrl}, Version: {response.VersionInfo}"); return(new Watch( Task.FromResult(response), Watch.NoOp)); }
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); }
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; }