/// <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); }