public InfoEventArgs(PacketHeader header, InfoPacket body) : base(header) { Info = body.Info; OnlineUsers = body.OnlineUsers; }
// Tries to grab a file and download it to our local machine public void GetFile(string filename) { // Init the get file state Console.WriteLine("Requesting file: {0}", filename); ReceiverState state = ReceiverState.RequestingFile; byte[] checksum = null; UInt32 fileSize = 0; UInt32 numBlocks = 0; UInt32 totalRequestedBlocks = 0; Stopwatch transferTimer = new Stopwatch(); // Small function to reset the transfer state Action ResetTransferState = new Action(() => { state = ReceiverState.RequestingFile; checksum = null; fileSize = 0; numBlocks = 0; totalRequestedBlocks = 0; _blockRequestQueue.Clear(); _blocksReceived.Clear(); transferTimer.Reset(); }); // Main loop _running = true; bool senderQuit = false; bool wasRunning = _running; while (_running) { // Check for some new packets (if there are some) _checkForNetworkMessages(); NetworkMessage nm = (_packetQueue.Count > 0) ? _packetQueue.Dequeue() : null; // In case the sender is shutdown, quit bool isBye = (nm == null) ? false : nm.Packet.IsBye; if (isBye) { senderQuit = true; } // The state switch (state) { case ReceiverState.RequestingFile: // Create the REQF RequestFilePacket REQF = new RequestFilePacket(); REQF.Filename = filename; // Send it byte[] buffer = REQF.GetBytes(); _client.Send(buffer, buffer.Length); // Move the state to waiting for ACK state = ReceiverState.WaitingForRequestFileACK; break; case ReceiverState.WaitingForRequestFileACK: // If it is an ACK and the payload is the filename, we're good bool isAck = (nm == null) ? false : (nm.Packet.IsAck); if (isAck) { AckPacket ACK = new AckPacket(nm.Packet); // Make sure they respond with the filename if (ACK.Message == filename) { // They got it, shift the state state = ReceiverState.WaitingForInfo; Console.WriteLine("They have the file, waiting for INFO..."); } else { ResetTransferState(); // Not what we wanted, reset } } break; case ReceiverState.WaitingForInfo: // Verify it's file info bool isInfo = (nm == null) ? false : (nm.Packet.IsInfo); if (isInfo) { // Pull data InfoPacket INFO = new InfoPacket(nm.Packet); fileSize = INFO.FileSize; checksum = INFO.Checksum; numBlocks = INFO.BlockCount; // Allocate some client side resources Console.WriteLine("Received an INFO packet:"); Console.WriteLine(" Max block size: {0}", INFO.MaxBlockSize); Console.WriteLine(" Num blocks: {0}", INFO.BlockCount); // Send an ACK for the INFO AckPacket ACK = new AckPacket(); ACK.Message = "INFO"; buffer = ACK.GetBytes(); _client.Send(buffer, buffer.Length); // Shift the state to ready state = ReceiverState.PreparingForTransfer; } break; case ReceiverState.PreparingForTransfer: // Prepare the request queue for (UInt32 id = 1; id <= numBlocks; id++) { _blockRequestQueue.Enqueue(id); } totalRequestedBlocks += numBlocks; // Shift the state Console.WriteLine("Starting Transfer..."); transferTimer.Start(); state = ReceiverState.Transfering; break; case ReceiverState.Transfering: // Send a block request if (_blockRequestQueue.Count > 0) { // Setup a request for a Block UInt32 id = _blockRequestQueue.Dequeue(); RequestBlockPacket REQB = new RequestBlockPacket(); REQB.Number = id; // Send the Packet buffer = REQB.GetBytes(); _client.Send(buffer, buffer.Length); // Some handy info Console.WriteLine("Sent request for Block #{0}", id); } // Check if we have any blocks ourselves in the queue bool isSend = (nm == null) ? false : (nm.Packet.IsSend); if (isSend) { // Get the data (and save it SendPacket SEND = new SendPacket(nm.Packet); Block block = SEND.Block; _blocksReceived.Add(block.Number, block); // Print some info Console.WriteLine("Received Block #{0} [{1} bytes]", block.Number, block.Data.Length); } // Requeue any requests that we haven't received if ((_blockRequestQueue.Count == 0) && (_blocksReceived.Count != numBlocks)) { for (UInt32 id = 1; id <= numBlocks; id++) { if (!_blocksReceived.ContainsKey(id) && !_blockRequestQueue.Contains(id)) { _blockRequestQueue.Enqueue(id); totalRequestedBlocks++; } } } // Did we get all the block we need? Move to the "transfer successful state." if (_blocksReceived.Count == numBlocks) { state = ReceiverState.TransferSuccessful; } break; case ReceiverState.TransferSuccessful: transferTimer.Stop(); // Things were good, send a BYE message Packet BYE = new Packet(Packet.Bye); buffer = BYE.GetBytes(); _client.Send(buffer, buffer.Length); Console.WriteLine("Transfer successful; it took {0:0.000}s with a success ratio of {1:0.000}.", transferTimer.Elapsed.TotalSeconds, (double)numBlocks / (double)totalRequestedBlocks); Console.WriteLine("Decompressing the Blocks..."); // Reconstruct the data if (_saveBlocksToFile(filename, checksum, fileSize)) { Console.WriteLine("Saved file as {0}.", filename); } else { Console.WriteLine("There was some trouble in saving the Blocks to {0}.", filename); } // And we're done here _running = false; break; } // Sleep Thread.Sleep(1); // Check for shutdown _running &= !_shutdownRequested; _running &= !senderQuit; } // Send a BYE message if the user wanted to cancel if (_shutdownRequested && wasRunning) { Console.WriteLine("User canceled transfer."); Packet BYE = new Packet(Packet.Bye); byte[] buffer = BYE.GetBytes(); _client.Send(buffer, buffer.Length); } // If the server told us to shutdown if (senderQuit && wasRunning) { Console.WriteLine("The sender quit on us, canceling the transfer."); } ResetTransferState(); // This also cleans up collections _shutdownRequested = false; // In case we shut down one download, but want to start a new one }
private void Info(InfoPacket packet) { Console.WriteLine(packet.Message + " Connected clients: " + packet.ConnectedClients); }