/// <summary> /// Manage the download of a file sended by a remote host /// </summary> /// <param name="client">TCPClient object</param> /// <param name="stream">NetworkStream of the client</param> /// <param name="ip">Remote Ip user</param> /// <param name="fileOriginal">File Name</param> /// <param name="dim">File lenght(bytes)</param> async Task ServeReceiveFile(TcpClient client, NetworkStream stream, string ip, string fileOriginal, long dim) { string filename = ""; FileStream file; // Wait the asyncronous operation to chec if the same file exists in the filesystem await semaphoreForFile.WaitAsync(); filename = Utility.PathTmp() + "\\" + fileOriginal; if (File.Exists(filename)) { string[] splits = filename.Split('.'); string[] files = Directory.GetFiles(Utility.PathTmp(), Utility.PathToFileName(splits[splits.Length - 2]) + "*" + splits[splits.Length - 1]); splits[splits.Length - 2] += files.Count() > 0 ? ("_" + files.Count()) : ""; filename = string.Join(".", splits); _referenceData.UpdateFileName(fileOriginal, Utility.PathToFileName(filename), ip, FileRecvStatus.YSEND); } file = File.Create(filename); Console.WriteLine($"{DateTime.Now.ToString()}\t - ServeReceive created file on path {filename}"); semaphoreForFile.Release(); // Start file dowload // --------------------------------------------------------------- byte[] bytes = new byte[bufferSize * 64]; bool first = true; bool noFlag = false; // dimFile = total file dimension // dataReceived = total bytes that aren't received yet long dataReceived = dim; int i = 0; uint estimatedTimePacketCount = 0; double numerator = 0.0; double estimateTime = 0.0; DateTime started = DateTime.Now; TimeSpan estimatedTime = TimeSpan.FromSeconds(0); try { while (((i = stream.Read(bytes, 0, bytes.Length)) != 0) && dataReceived >= 0) { double dataReceivedJet = 0.0f; if (first) { noFlag = _referenceData.CheckAndUpdateRecvFileStatus(ip, fileOriginal); if (!noFlag) { await MainWindow.main.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => { MainWindow.main.AddOrUpdateListFile(ip, fileOriginal, FileRecvStatus.INPROGRESS, null, null); })); } first = false; } else { noFlag = _referenceData.CheckRecvFileStatus(ip, fileOriginal, FileRecvStatus.NSEND); } if (noFlag) { throw new Exception("File is rejected by remote host"); } if (dataReceived > 0 && dataReceived < i) { file.Write(bytes, 0, Convert.ToInt32(dataReceived)); dataReceivedJet = 100f; } else { file.Write(bytes, 0, i); dataReceivedJet = Math.Ceiling((double)(dim - dataReceived) / ((double)dim) * 100); } dataReceived -= i; if (estimatedTimePacketCount < 5) { numerator += (double)(dim - dataReceived); estimatedTimePacketCount++; } else { TimeSpan elapsedTime = DateTime.Now - started; estimateTime = elapsedTime.TotalSeconds * dataReceived / numerator; estimatedTime = TimeSpan.FromSeconds(estimateTime); numerator = 0.0; estimatedTimePacketCount = 0; } string estimatedTimeJet = string.Format("{00:00}", estimatedTime.Minutes) + ":" + string.Format("{00:00}", estimatedTime.Seconds) + ":" + string.Format("{00:00}", estimatedTime.Milliseconds); await MainWindow.main.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => { MainWindow.main.AddOrUpdateListFile(ip, fileOriginal, FileRecvStatus.INPROGRESS, estimatedTimeJet, dataReceivedJet); })); } file.Close(); // End file download, start unzip! // --------------------------------------------------------------- string fileNameToProcess = filename; string ipUser = ip; // Create a new task to execute the unzip asynchronously await Task.Run(() => { FileRecvStatus?currentStatusFile = _referenceData.GetStatusRecvFileForUser(ipUser, Utility.PathToFileName(fileNameToProcess)); if (currentStatusFile == null) { return; } if (currentStatusFile.Value == FileRecvStatus.NSEND) { try { File.Delete(fileNameToProcess); } catch (Exception e) { Console.WriteLine($"{DateTime.Now.ToString()}\t - ExtractFileToSavePath Exception - {e.GetType()} {e.Message}"); obj.Release(); } } else { try { string savePathLocalUser = _referenceData.GetInfoLocalUser().SavePath; // Create directory if (fileNameToProcess.Contains("Dir")) { string nameFile = Utility.PathToFileName(fileNameToProcess); nameFile = fileNameToProcess.Replace("_" + ipUser.Replace(".", "_"), String.Empty); // Get directory name string[] parts = nameFile.Split('_'); nameFile = nameFile.Replace(parts[0] + "_", string.Empty); string nameDir = nameFile.Replace("_" + parts[parts.Length - 1], string.Empty); string destPath = Path.Combine(savePathLocalUser, nameDir); semaphoreForFile.Wait(); if (!Directory.Exists(destPath)) { Directory.CreateDirectory(destPath); } else { int numb = Directory.GetDirectories(savePathLocalUser, nameDir + "*").Count(); Directory.CreateDirectory(destPath + "_(" + numb + ")"); destPath += "_(" + numb + ")"; } // Unzip files ZipFile.ExtractToDirectory(fileNameToProcess, destPath); _referenceData.UpdateStatusRecvFileForUser(ipUser, Utility.PathToFileName(fileNameToProcess), FileRecvStatus.RECIVED); MainWindow.main.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => { MainWindow.main.AddOrUpdateListFile(ip, fileOriginal, FileRecvStatus.RECIVED, "-", 100); MainWindow.main.StopNotify(); })); semaphoreForFile.Release(); } else if (fileNameToProcess.Contains("Files")) { // In case of a zip full of files using (ZipArchive archive = ZipFile.OpenRead(fileNameToProcess)) { // Check of each file if it already exists a file with the same name semaphoreForFile.Wait(); foreach (ZipArchiveEntry entry in archive.Entries) { string nameFileToExtract = ""; if (File.Exists(Path.Combine(savePathLocalUser, entry.Name))) { string[] parts = entry.Name.Split('.'); string extension = parts[parts.Length - 1]; parts = parts.Take(parts.Count() - 1).ToArray(); string name = String.Join(".", parts); int numb = Directory.GetFiles(savePathLocalUser, name + "*" + extension).Length; nameFileToExtract = name + "_(" + numb + ")." + extension; } else { nameFileToExtract = entry.Name; } entry.ExtractToFile(Path.Combine(savePathLocalUser, nameFileToExtract)); } _referenceData.UpdateStatusRecvFileForUser(ipUser, Utility.PathToFileName(fileNameToProcess), FileRecvStatus.RECIVED); MainWindow.main.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => { MainWindow.main.AddOrUpdateListFile(ip, fileOriginal, FileRecvStatus.RECIVED, "-", 100); MainWindow.main.StopNotify(); })); semaphoreForFile.Release(); } } } catch (Exception e) { Console.WriteLine($"{DateTime.Now.ToString()}\t - Exception on unzip file received - {e.GetType()} {e.Message}"); File.Delete(fileNameToProcess); FileRecvStatus status = FileRecvStatus.NSEND; _referenceData.UpdateStatusRecvFileForUser(ipUser, Utility.PathToFileName(fileNameToProcess), status); MainWindow.main.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => { MainWindow.main.AddOrUpdateListFile(ip, fileOriginal, status, "-", 0); })); if (semaphoreForFile.CurrentCount < 1) { semaphoreForFile.Release(); } } finally { obj.Release(); } } }); await obj.WaitAsync(); } catch (Exception e) { Console.WriteLine($"{DateTime.Now.ToString()}\t - ServeReceiveFile Exception - {e.GetType()} {e.Message}"); file.Close(); File.Delete(filename); } }
/// <summary> /// Questo metodo conferma o rifiuta la ricezione di un file da parte di un host remoto. /// Seguito dalla conferma ci sarà il nome del file su cui è stata fatta la scelta /// </summary> /// <param name="ip">Ip dell'host su cui si è eseguita la scelta</param> /// <param name="type">La scela effettuata</param> public async Task SendResponse(string ip, string nameFile, PacketType type) { if (type != PacketType.YFILE && type != PacketType.NFILE) { return; } if (!_referenceData.UpdateStatusRecvFileForUser(ip, nameFile, type == PacketType.YFILE ? FileRecvStatus.YSEND : FileRecvStatus.NSEND)) { throw new Exception("File don't exists in collection"); } int attempts = 0; // In case of exception resend the packet three times do { TcpClient client = null; NetworkStream stream = null; try { attempts++; client = new TcpClient(); await client.ConnectAsync(ip, SharedInfo.TCPPort).ConfigureAwait(false); byte[] bytes = new byte[1 + 256]; bytes[0] = (byte)type; UTF8Encoding encorder = new UTF8Encoding(); encorder.GetBytes(nameFile).CopyTo(bytes, 1); stream = client.GetStream(); await stream.WriteAsync(bytes, 0, 257).ConfigureAwait(false); break; } catch (SocketException e) { Console.WriteLine($"{DateTime.Now.ToString()}\t - SocketException on SendResponse - {e.Message}"); // If the remote host was offline, try to resend it for three times if (_referenceData.GetUserStatus(ip).Equals("offline")) { break; } else if (attempts == 3) { break; } else { await Task.Delay(10).ConfigureAwait(false); } } catch (Exception e) { Console.WriteLine($"{DateTime.Now.ToString()}\t - Exception on SendResponse - {e.Message}"); if (attempts == 3) { break; } else { await Task.Delay(10).ConfigureAwait(false); } } finally { client.Close(); stream.Close(); } if (attempts == 3 && _referenceData.GetUserStatus(ip).Equals("offline")) { break; } } while (true); }