/// <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> /// Function to receive a deletion request of files on the receiver's computer /// </summary> /// <param name="message">The message with the chunks which has to be deleted</param> private void ReceivedDeletionRequest(FileDeletionMessage message) { DiskHelper.ConsoleWrite("Deletion Message Received."); if (!message.type.Equals(TypeCode.REQUEST)) { return; } if (!message.statusCode.Equals(StatusCode.OK)) { return; } string path = _path + @".hidden\" + message.fromUuid + @"\" + message.fullFileHash + @"\" + message.fileHash; DiskHelper.ConsoleWrite(path); if (File.Exists(path)) { File.Delete(path); message.statusCode = StatusCode.ACCEPTED; message.CreateReply(); message.Send(message.port); } else { message.statusCode = StatusCode.FILE_NOT_FOUND; message.CreateReply(); message.Send(message.port); } }
/// <summary> /// Function to receive download message /// </summary> /// <param name="downloadMessage">The message which has to be received</param> private void ReceivedDownloadMessage(DownloadMessage downloadMessage) { if (downloadMessage.type.Equals(TypeCode.REQUEST)) { string path = _path + @".hidden\" + downloadMessage.fromUuid + @"\" + downloadMessage.fullFileName + @"\" + downloadMessage.filehash; if (downloadMessage.statusCode == StatusCode.OK) { if (File.Exists(path)) { downloadMessage.CreateReply(); downloadMessage.statusCode = StatusCode.ACCEPTED; downloadMessage.Send(downloadMessage.port); Console.WriteLine("Response send"); } else { Console.WriteLine("File not found"); downloadMessage.CreateReply(); downloadMessage.statusCode = StatusCode.FILE_NOT_FOUND; downloadMessage.Send(downloadMessage.port); } } else if (downloadMessage.statusCode.Equals(StatusCode.ACCEPTED)) { var sender = new ChunkSender(downloadMessage.fromIp, downloadMessage.port); sender.Send(path); DiskHelper.ConsoleWrite("File send " + downloadMessage.filehash); } } }
/// <summary> /// This is a helper function for the fetching function, this is responsible for downloading the chunk. /// </summary> /// <param name="fullFileName">Full name of the file.</param> /// <param name="port">Port for which to download from.</param> private bool Downloader(string fullFileName, int port) { int timeout = 3000; int timeoutCounter = 0; var server = new TcpListener(this._ip, port); try{ server.AllowNatTraversal(true); server.Server.ReceiveTimeout = 1000; server.Server.SendTimeout = 1000; server.Start(); }catch (Exception e) { Logger.Error(e); return(false); } while (!server.Pending()) { if (timeoutCounter >= timeout) { server.Stop(); return(false); } timeoutCounter++; Thread.Sleep(5); } try { var client = server.AcceptTcpClient(); client.ReceiveTimeout = 1000; client.Client.ReceiveTimeout = 1000; using (NetworkStream stream = client.GetStream()){ using (var fileStream = File.Open(_path + fullFileName + @"\" + _hash, FileMode.OpenOrCreate, FileAccess.Write)){ DiskHelper.ConsoleWrite("Creating file: " + this._hash); int i; while ((i = stream.Read(_buffer, 0, _buffer.Length)) > 0) { fileStream.Write(_buffer, 0, (i < _buffer.Length) ? i : _buffer.Length); } fileStream.Close(); } stream.Close(); _ports.Release(port); return(true); } } catch (Exception e) { DiskHelper.ConsoleWrite("The peer requested went offline in Downloader." + e); return(false); } }
/// <summary> /// Function to receive peers from one or your peers peer list /// </summary> /// <param name="message">It is the message which is sent to the receiver</param> private void ReceivedPeerFetch(PeerFetcherMessage message) { if (message.type.Equals(TypeCode.REQUEST)) { var outgoing = new List <Peer>(); var incoming = message.peers; // Adding sender to list if (!InPeerList(message.fromUuid, _peers)) { _peers.TryAdd(message.fromUuid, new Peer(message.fromUuid, message.fromIp)); } //Checks whether a incomming peer exists in the peerlist. foreach (var incomingPeer in incoming) { if (InPeerList(incomingPeer.GetUuid(), _peers)) { break; } _peers.TryAdd(incomingPeer.GetUuid(), incomingPeer); DiskHelper.ConsoleWrite("Peer added: " + incomingPeer.GetUuid()); } foreach (var outGoingPeer in _peers) { if (InPeerList(outGoingPeer.Value.GetUuid(), incoming)) { break; } if (outGoingPeer.Value.GetUuid() == message.fromUuid) { break; } outgoing.Add(outGoingPeer.Value); } message.CreateReply(); message.peers = outgoing; message.Send(); } else { // Rechieved response foreach (Peer incomingPeer in message.peers) { if (InPeerList(incomingPeer.GetUuid(), _peers)) { break; } if ((IdHandler.GetUuid().Equals(incomingPeer.GetUuid()))) { break; } _peers.TryAdd(incomingPeer.GetUuid(), incomingPeer); Console.WriteLine("Peer added: " + incomingPeer.GetUuid()); } } }
private void RestoreOriginalFile(string path, P2PFile fileInformation) { DiskHelper.ConsoleWrite("File exist"); string pathWithoutExtension = (_path + @".hidden\incoming\" + fileInformation.hash); //Merge files var splitterLibrary = new SplitterLibrary(); if (!splitterLibrary.MergeFiles(_path + @".hidden\incoming\" + fileInformation.hash + @"\", pathWithoutExtension + ".aes", fileInformation.GetChunksAsString())) { _queue.Enqueue(fileInformation); return; } // Decrypt file var decryption = new FileEncryption(pathWithoutExtension, ".lzma"); if (!decryption.DoDecrypt(IdHandler.GetKeyMold())) { _queue.Enqueue(fileInformation); return; } DiskHelper.ConsoleWrite("File decrypted"); File.Delete(path); // Decompress file string pathToFileForCopying = Compressor.DecompressFile(pathWithoutExtension + ".lzma", pathWithoutExtension); DiskHelper.ConsoleWrite("File decompressed"); foreach (string filePath in _index.GetEntry(_fileHash).paths) { if (!Directory.Exists(Path.GetDirectoryName(filePath))) { Directory.CreateDirectory(Path.GetDirectoryName(filePath) ?? throw new NullReferenceException()); } try{ if (!File.Exists(filePath)) { File.Copy(pathToFileForCopying, filePath); DiskHelper.ConsoleWrite($"File saved to: {filePath}"); } } catch (Exception e) { logger.Error(e); } } }
/// <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> /// Toggles whether a peer is online. /// </summary> /// <param name="online">Boolean of whether the peer got online, or offline.</param> public void SetOnline(bool online) { if (online != this._online) { if (online) { DiskHelper.ConsoleWrite(this._ip + " - is now online!"); rankHandler.UpdateUptime(this); PeerSwitchedOnline?.Invoke(); } else { DiskHelper.ConsoleWrite(this._ip + " - is now offline!"); rankHandler.UpdateUptime(this); } } this._online = online; this._pingsWithoutResponse = 0; }
/// <summary> /// Handles the connection, creates and downloads the file. /// </summary> private void ConnectionHandler() { string path = this._path + this._filename; try{ var client = _server.AcceptTcpClient(); client.ReceiveTimeout = 5000; using (NetworkStream stream = client.GetStream()){ DiskHelper.ConsoleWrite(@"Receiving file"); using (var fileStream = File.Open(path, FileMode.OpenOrCreate, FileAccess.Write)){ DiskHelper.ConsoleWrite("Creating file: " + this._filename); int i; while ((i = stream.Read(_buffer, 0, _buffer.Length)) > 0) { fileStream.Write(_buffer, 0, (i < _buffer.Length) ? i : _buffer.Length); } DiskHelper.ConsoleWrite(@"File done downloading"); fileStream.Close(); } stream.Close(); } client.Close(); } catch (InvalidOperationException e) { logger.Fatal(e); } catch (Exception e) { logger.Error(e); } finally{ Stop(); } }
/// <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); }
/// <summary> /// Main running function for UploadManager, needs to be called for it to run. /// </summary> public void Run() { _isStopped = false; this._waitHandle.Set(); while (_isRunning) { this._waitHandle.WaitOne(); if (!_isRunning) { break; } while (this._queue.TryDequeue(out P2PFile file)) { bool uploaded = true; if (!_peers.Any(p => p.Value.IsOnline())) { this._queue.Enqueue(file); break; } if (!_isRunning) { this._queue.Enqueue(file); break; } string filePath = file.paths[0]; string compressedFilePath = this._path + @".hidden\" + file.hash; // Compress file bool compressionCompleted = Compressor.CompressFile(filePath, compressedFilePath); if (!compressionCompleted) { this._queue.Enqueue(file); continue; } // Encrypt file var encryption = new FileEncryption(compressedFilePath, ".lzma"); bool encryptionCompleted = encryption.DoEncrypt(IdHandler.GetKeyMold()); if (!encryptionCompleted) { this._queue.Enqueue(file); continue; } _hiddenFolder.Remove(compressedFilePath + ".lzma"); string encryptedFilePath = compressedFilePath + ".aes"; // Initialize splitter var splitter = new SplitterLibrary(); List <string> chunks = splitter.SplitFile(encryptedFilePath, file.hash, _path + @".hidden\splitter\"); file.AddChunk(chunks); FileUploader uploader = new FileUploader(_ports, _peers); int i = 0; foreach (var chunk in file.chunks) { string path = _path + @".hidden\splitter\" + chunk.hash; //3 is used, because the network is relatively small. 10 is the default. if (!uploader.Push(chunk, path, 3, i)) { uploaded = false; } i++; } if (!uploaded) { this._queue.Enqueue(file); } if (uploaded) { Console.WriteLine(); DiskHelper.ConsoleWrite($"The file {file.hash} was successfully sent to all \n"); } } this._waitHandle.Reset(); } _isStopped = true; }
static void Main() { bool running = true; bool firstRun = true; MyForm torPdos = new MyForm(); //If the ''Path'' variable is not set, the GUI is run to set this up. if (string.IsNullOrEmpty(DiskHelper.GetRegistryValue("Path"))) { Application.Run(torPdos); } //If the ''Path'' variable is set, but the userdata file does not exist, //the GUI is run to create this. else if (File.Exists(DiskHelper.GetRegistryValue("Path") + @".hidden\userdata") == false) { Application.Run(torPdos); } //Gets the local IP and the path to the users TorPDos-folder. string ownIp = NetworkHelper.GetLocalIpAddress(); string path = (DiskHelper.GetRegistryValue("Path")); //Starts the communication with the user, and ensures that //the user logs in. DiskHelper.ConsoleWrite("Welcome to TorPdos!"); Console.WriteLine(@"Please login by typing: login [PASSWORD] or gui"); while (running) { string console = Console.ReadLine(); if (console != null) { string[] param = console.Split(' '); //Close program if (console.Equals("quit") || console.Equals("q")) { Console.WriteLine(@"Quitting..."); _idx.Save(); _idx.Stop(); _p2P.SavePeer(); _p2P.Stop(); running = false; Console.WriteLine(" \n Press any button to quit!"); } else { //Handles the login of the user through the console. while (IdHandler.GetUuid() == null) { if (console.StartsWith("login") && param.Length == 2) { if (IdHandler.GetUuid(param[1]) == "Invalid Password") { Console.WriteLine(); Console.WriteLine(@"Invalid password, try again"); Console.WriteLine(@"Please login by typing: login [PASSWORD] or gui"); console = Console.ReadLine(); if (console != null) { param = console.Split(' '); } } //Gives the opportunity to open the GUI for login. } else if (console.Equals("gui")) { Application.Run(torPdos); } else { Console.WriteLine(); Console.WriteLine(@"Error! Try again"); Console.WriteLine(@"Please login by typing: login [PASSWORD] or gui"); console = Console.ReadLine(); param = console.Split(' '); } } //Handles the creation or loading of all the necessary //files and directories. if (firstRun) { // Load Index if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } _idx = new Index(path); torPdos._idx = _idx; // Prepare P2PNetwork try{ _p2P = new Network(25565, _idx, path); _p2P.Start(); torPdos._p2P = _p2P; } catch (SocketException) { Application.Run(torPdos); } _idx.Load(); _idx.FileAdded += Idx_FileAdded; _idx.FileChanged += Idx_FileChanged; _idx.FileDeleted += Idx_FileDeleted; _idx.FileMissing += Idx_FileMissing; if (!_idx.Load()) { _idx.BuildIndex(); } _idx.Start(); Console.WriteLine(@"Integrity check initialized..."); _idx.MakeIntegrityCheck(); Console.WriteLine(@"Integrity check finished!"); Console.WriteLine(@"Local: " + ownIp); Console.WriteLine(@"Free space on C: " + DiskHelper.GetTotalAvailableSpace("C:\\")); Console.WriteLine(@"UUID: " + IdHandler.GetUuid()); firstRun = false; //Restart loop to take input continue; } // Handle input if (console.StartsWith("add") && param.Length == 3) { _p2P.AddPeer(param[1].Trim(), param[2].Trim()); } else if (console.Equals("reindex")) { _idx.ReIndex(); } else if (console.Equals("gui")) { MyForm torPdos2 = new MyForm(); Application.Run(torPdos2); } else if (console.Equals("status")) { _idx.Status(); } else if (console.Equals("idxsave")) { _idx.Save(); } else if (console.Equals("peersave")) { _p2P.SavePeer(); } else if (console.Equals("ping")) { _p2P.Ping(); } else if (console.Equals("integrity")) { _idx.MakeIntegrityCheck(); } else if (console.Equals("list")) { List <Peer> peers = _p2P.GetPeerList(); Console.WriteLine(); Console.WriteLine(@"### Your Peerlist contains ###"); if (peers.Count > 0) { foreach (Peer peer in peers) { RankingHandler rankingHandler = new RankingHandler(); rankingHandler.GetRank(peer); Console.WriteLine(@"(R:" + peer.Rating + @") " + peer.GetUuid() + @" - " + peer.GetIp() + @" - " + (peer.IsOnline() ? "Online" : "Offline")); Console.WriteLine(@"disk: " + Convert.ToInt32((peer.diskSpace / 1e+9)) + @"GB | avgPing: " + peer.GetAverageLatency() + "\n"); } } else { Console.WriteLine(@"The list is empty..."); } Console.WriteLine(); } else if (console.Trim().Equals("")) { } else { Console.WriteLine(@"Unknown command"); } } } } Console.ReadKey(); }