static void Main(string[] args) { Program prog = new Program(args); if (prog.ShowUsage) { Usage(); return; } if (prog.ArgsOk) { FrameDisplay frameDisplay = new FrameDisplay(); try { prog.Run(frameDisplay); } finally { // Ensure frameDisplay thread terminates. frameDisplay.Stop(); } } else { Usage(); } }
public void Run(FrameDisplay frameDisplay) { int connectionPollTimeSecMs = 250; TcpClient socket = null; PacketBuffer packetBuffer = null; CollatedPacketDecoder collatedDecoder = new CollatedPacketDecoder(); BinaryWriter recordingWriter = null; #if PACKET_TIMING Stopwatch timer = new Stopwatch(); #endif // PACKET_TIMING bool once = true; Console.CancelKeyPress += new ConsoleCancelEventHandler(ControlCHandler); if (!Quiet) { Console.WriteLine(string.Format("Connecting to {0}", ServerEndPoint)); } while (!Quit && (Persist || once)) { once = false; // First try establish a connection. while (!Quit && !Connected) { if ((socket = AttemptConnection()) != null) { #if PACKET_TIMING timer.Reset(); timer.Start(); #endif // PACKET_TIMING TotalFrames = 0u; frameDisplay.Reset(); if (!Quiet) { frameDisplay.Start(); } recordingWriter = CreateOutputWriter(); if (recordingWriter != null) { Connected = true; // Create a new packet buffer for this connection. packetBuffer = new PacketBuffer(4 * 1024); } Log.Flush(); } else { Log.Flush(); // Wait the timeout period before attempting to reconnect. System.Threading.Thread.Sleep(connectionPollTimeSecMs); } } // Read while connected or data still available. while (!Quit && socket != null && (TcpClientUtil.Connected(socket) || socket.Available > 0)) { // We have a connection. Read messages while we can. if (socket.Available > 0) { // Data available. Read from the network stream into a buffer and attempt to // read a valid message. packetBuffer.Append(socket.GetStream(), socket.Available); PacketBuffer completedPacket; bool exportPacket = true; bool crcOk = true; while ((completedPacket = packetBuffer.PopPacket(out crcOk)) != null || !crcOk) { if (crcOk) { if (packetBuffer.DroppedByteCount != 0) { Console.Error.WriteLine("Dropped {0} bad bytes", packetBuffer.DroppedByteCount); packetBuffer.DroppedByteCount = 0; } if (DecodeMode == Mode.Passthrough) { completedPacket.ExportTo(recordingWriter); // Approximate packets as frames. Not exactly correct though. if (completedPacket.Header.RoutingID == (ushort)RoutingID.Control) { if (completedPacket.Header.MessageID == (ushort)ControlMessageID.EndFrame) { ++TotalFrames; frameDisplay.IncrementFrame(); #if PACKET_TIMING if (TotalFrames >= PacketLimit) { timer.Stop(); Quit = true; } #endif // PACKET_TIMING } } continue; } // Decode and decompress collated packets. This will just return the same packet // if not collated. collatedDecoder.SetPacket(completedPacket); while ((completedPacket = collatedDecoder.Next()) != null) { //Console.WriteLine("Msg: {0} {1}", completedPacket.Header.RoutingID, completedPacket.Header.MessageID); switch (completedPacket.Header.RoutingID) { case (ushort)RoutingID.Control: ushort controlMessageId = completedPacket.Header.MessageID; if (controlMessageId == (ushort)ControlMessageID.EndFrame) { ++TotalFrames; frameDisplay.IncrementFrame(); #if PACKET_TIMING if (TotalFrames >= PacketLimit) { timer.Stop(); Quit = true; } #endif // PACKET_TIMING } break; case (ushort)RoutingID.ServerInfo: NetworkReader packetReader = new NetworkReader(completedPacket.CreateReadStream(true)); _serverInfo.Read(packetReader); exportPacket = false; break; default: break; } if (exportPacket) { completedPacket.ExportTo(recordingWriter); } } } else { Console.Error.WriteLine("CRC Failure"); // TODO: Log CRC failure. } } Log.Flush(); } else { Log.Flush(); System.Threading.Thread.Sleep(0); } } frameDisplay.Stop(); if (packetBuffer != null && packetBuffer.DroppedByteCount != 0) { Console.Error.WriteLine("Dropped {0} bad bytes", packetBuffer.DroppedByteCount); packetBuffer.DroppedByteCount = 0; } if (recordingWriter != null) { FinaliseOutput(recordingWriter, TotalFrames); recordingWriter.Flush(); recordingWriter.Close(); recordingWriter = null; } if (!Quiet) { Console.WriteLine("Connection closed"); } // Disconnected. if (socket != null) { socket.Close(); socket = null; } Connected = false; // GC to force flushing streams and collect other resource. GC.Collect(); } #if PACKET_TIMING Console.WriteLine($"Processed {PacketLimit} packets in {timer.ElapsedMilliseconds}ms"); #endif // PACKET_TIMING }