/// <summary> /// Handles the deletion of a chunk of the file /// </summary> /// <param name="currentFileChunk">The P2PChunk to be deleted</param> /// <param name="currentFile">The P2PFile to wich the chunk belongs</param> /// <returns></returns> public bool ChunkDeleter(P2PChunk currentFileChunk, P2PFile currentFile){ Listener listener = new Listener(this._port); int lastIndex = currentFileChunk.peers.Count - 1; //Sends a delete message to every peer with the chunk for (int i = lastIndex; i >= 0; i--) { if (_peers.TryGetValue(currentFileChunk.peers[i], out Peer currentReceiver)) { if (!currentReceiver.IsOnline()){ return false; } var deletionMessage = new FileDeletionMessage(currentReceiver) { type = TypeCode.REQUEST, statusCode = StatusCode.OK, port = _port, fileHash = currentFileChunk.hash, fullFileHash = currentFile.hash }; //Sends the message and waits for a response, //which will then overwrite the original sent message if (listener.SendAndAwaitResponse(ref deletionMessage, 2000)) { if (deletionMessage.type.Equals(TypeCode.RESPONSE)) { currentFileChunk.RemovePeer(deletionMessage.fromUuid); if (currentFileChunk.peers.Count == 0) { currentFile.RemoveChunk(currentFileChunk.hash); } if (deletionMessage.statusCode.Equals(StatusCode.FILE_NOT_FOUND)) { DiskHelper.ConsoleWrite("File not found at peer"); } } } } } return true; }
/// <summary> /// Pushes the inputted chunk to the network, sending it the required amount of peers. /// </summary> /// <param name="chunk">The chunk to push to the network</param> /// <param name="chunkPath">String path to the chunks</param> /// <param name="numberOfRecevingPeers">The number of peers to send the file to, /// this will be the amount of receivers, unless the network is smaller than the given input.</param> /// <param name="receiverOffset">The offset for whom to send the files to, this determines the spacing of the chunks on the peerlist.</param> /// <returns>Boolean of whether the push was a success.</returns> public bool Push(P2PChunk chunk, string chunkPath, int numberOfRecevingPeers = 10, int receiverOffset = 0) { this._port = _ports.GetAvailablePort(); List <Peer> peers = this.GetPeers(); FileInfo fileInfo = new FileInfo(chunkPath); Listener listener = new Listener(this._port); bool sendToAll = true; int listLength = peers.Count; int peerCount; int numberOfReceivers = Math.Min(numberOfRecevingPeers, listLength); for (peerCount = 0; peerCount < numberOfReceivers; peerCount++) { Peer currentPeer = peers[(peerCount + receiverOffset) % listLength]; var upload = new UploadMessage(currentPeer) { filesize = fileInfo.Length, fullFilename = chunk.originalHash, chunkHash = chunk.hash, path = chunkPath, port = this._port }; if (listener.SendAndAwaitResponse(ref upload, 2000)) { if (upload.statusCode == StatusCode.ACCEPTED) { ChunkSender sender = new ChunkSender(currentPeer.StringIp, upload.port); if (sender.Send(chunkPath)) { DiskHelper.ConsoleWrite($"The chunk {chunk.hash} was sent to {currentPeer.GetUuid()}"); chunk.AddPeer(currentPeer.GetUuid()); } else { sendToAll = false; } _ports.Release(upload.port); } } } _ports.Release(this._port); return(sendToAll); }
/// <summary> /// Fetching function, this fetches the given chunk from the network, returns true if the chunk is fetched. /// </summary> /// <param name="chunk">The chunk wanted to download.</param> /// <param name="fullFileName">The name of the full file.</param> /// <returns>Rather the chunk has been fetched.</returns> public bool Fetch(P2PChunk chunk, string fullFileName) { _port = _ports.GetAvailablePort(); _hash = chunk.hash; _peersToAsk = chunk.peers; Listener listener = new Listener(this._port); foreach (var peer in _peersToAsk) { if (!_peers.TryGetValue(peer, out Peer currentPeer)) { break; } if (currentPeer.IsOnline()) { var download = new DownloadMessage(currentPeer) { port = this._port, fullFileName = chunk.originalHash, filehash = _hash }; // Sends the download message and waits for a // "response" download message to be received. // Then changed 'download' to this message and // returns true. If a response is not received // within time, it returns false. if (listener.SendAndAwaitResponse(ref download, 3000)) { // If the download is accepted, a receiver is // started and the port of the receiver is // sent to the peer. if (download.statusCode == StatusCode.ACCEPTED) { int receiverPort = _ports.GetAvailablePort(); download.CreateReply(); download.type = Messages.TypeCode.REQUEST; download.statusCode = StatusCode.ACCEPTED; download.port = receiverPort; if (!Directory.Exists(_path + fullFileName + @"\")) { Directory.CreateDirectory(_path + fullFileName + @"\"); } download.Send(); if (!currentPeer.IsOnline()) { DiskHelper.ConsoleWrite("The peer requested went offline."); continue; } DiskHelper.ConsoleWrite("FileReceiver opened"); if (!Downloader(fullFileName, receiverPort)) { return(false); } _ports.Release(download.port); break; } else if (download.statusCode == StatusCode.FILE_NOT_FOUND) { Console.WriteLine("File not found at peer."); chunk.peers.Remove(download.fromUuid); } } } } if (File.Exists(_path + fullFileName + @"\" + _hash)) { if (CheckDownloadHash(_path + fullFileName + @"\" + _hash, _hash)) { DiskHelper.ConsoleWrite(@"Chunk done downloading"); return(true); } } return(false); }