예제 #1
0
        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
        }
예제 #2
0
        private IEnumerator Run()
        {
            // Reconnection attempts so we don't hammer the system on failure.
            float        connectionPollTimeSec = 0.25f;
            TcpClient    socket       = null;
            PacketBuffer packetBuffer = new PacketBuffer(4 * 1024);

            System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();
            ClientConnector connector          = null;

            while (!_quitFlag)
            {
                // First try establish a connection.
                while (!_quitFlag && !_connection.Connected)
                {
                    if (connector == null)
                    {
                        connector = new ClientConnector(_connection.EndPoint);
                    }

                    if (!connector.Connecting)
                    {
                        if (connector.Connected)
                        {
                            socket                = connector.Accept();
                            connector             = null;
                            _connection.Connected = true;
                            Status                = NetworkThreadStatus.Connected;
                            _currentFrame         = _totalFrames = 0u;
                            _packetQueue.Enqueue(BuildResetPacket());
                        }
                        else
                        {
                            connector.Abort();
                            connector = null;
                            if (!_connection.AutoReconnect)
                            {
                                // Failed connection and no auto reconnect.
                                Status = NetworkThreadStatus.ConnectionFailed;
                                break;
                            }
                        }
                    }

                    if (socket == null)
                    {
                        // Wait the timeout period before attempting to reconnect.
                        yield return(Workthread.CreateWait(connectionPollTimeSec));
                    }
                }

                timer.Start();
                // Read while connected.
                while (!_quitFlag && TcpClientUtil.Connected(socket))
                {
                    // 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         crcOk = true;
                        while ((completedPacket = packetBuffer.PopPacket(out crcOk)) != null || !crcOk)
                        {
                            if (crcOk)
                            {
                                // Decode and decompress collated packets. This will just return the same packet
                                // if not collated.
                                _collatedDecoder.SetPacket(completedPacket);
                                while ((completedPacket = _collatedDecoder.Next()) != null)
                                {
                                    if (completedPacket.Header.RoutingID == (ushort)RoutingID.Control)
                                    {
                                        ushort controlMessageId = completedPacket.Header.MessageID;
                                        if (controlMessageId == (ushort)ControlMessageID.EndFrame)
                                        {
                                            timer.Stop();
                                            FrameTime = timer.ElapsedMilliseconds * 1e-3f;
                                            timer.Reset();
                                            timer.Start();
                                            ++_currentFrame;
                                            ++_totalFrames;
                                        }
                                    }

                                    _packetQueue.Enqueue(completedPacket);
                                }
                            }
                            else
                            {
                                // TODO: Log CRC failure.
                            }
                        }
                    }
                    else
                    {
                        yield return(null);
                    }
                }

                // Disconnected.
                if (socket != null)
                {
                    socket.LingerState.Enabled = false;
                    socket.Close();
                    socket = null;
                }
                if (_connection.Connected)
                {
                    Status = NetworkThreadStatus.Disconnected;
                    _connection.Connected = false;
                }

                if (!_connection.AutoReconnect)
                {
                    break;
                }
                Status = NetworkThreadStatus.Reconnecting;
            }
        }
예제 #3
0
        private IEnumerator Run()
        {
            // Reconnection attempts so we don't hammer the system on failure.
            float        connectionPollTimeSec = 0.25f;
            TcpClient    socket       = null;
            PacketBuffer packetBuffer = new PacketBuffer(4 * 1024);

            System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();
            ClientConnector connector          = null;

            while (!_quitFlag)
            {
                // First try establish a connection.
                while (!_quitFlag && !_connection.Connected)
                {
                    if (connector == null)
                    {
                        connector = new ClientConnector(_connection.EndPoint);
                    }

                    if (!connector.Connecting)
                    {
                        if (connector.Connected)
                        {
                            socket                = connector.Accept();
                            connector             = null;
                            _connection.Connected = true;
                            Status                = NetworkThreadStatus.Connected;
                            _currentFrame         = _totalFrames = 0u;
                            _packetQueue.Enqueue(BuildResetPacket());
                        }
                        else
                        {
                            connector.Abort();
                            connector = null;
                            if (!_connection.AutoReconnect)
                            {
                                // Failed connection and no auto reconnect.
                                Status = NetworkThreadStatus.ConnectionFailed;
                                break;
                            }
                        }
                    }

                    if (socket == null)
                    {
                        // Wait the timeout period before attempting to reconnect.
                        yield return(Workthread.CreateWait(connectionPollTimeSec));
                    }
                }

                timer.Start();
                // Read while connected.
                while (!_quitFlag && TcpClientUtil.Connected(socket))
                {
                    // 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         crcOk = true;
                        while ((completedPacket = packetBuffer.PopPacket(out crcOk)) != null || !crcOk)
                        {
                            if (crcOk)
                            {
                                // Decode and decompress collated packets. This will just return the same packet
                                // if not collated.
                                _collatedDecoder.SetPacket(completedPacket);
                                while ((completedPacket = _collatedDecoder.Next()) != null)
                                {
                                    if (completedPacket.Header.RoutingID == (ushort)RoutingID.Control)
                                    {
                                        ushort controlMessageId = completedPacket.Header.MessageID;
                                        if (controlMessageId == (ushort)ControlMessageID.EndFrame)
                                        {
                                            // Add a frame flush flag to every end frame message to ensure the render thread renders.
                                            // TODO: consider a way to frame skip in a live visualisation link.
                                            byte[] packetData   = completedPacket.Data;
                                            int    memberOffset = PacketHeader.Size + Marshal.OffsetOf(typeof(ControlMessage), "ControlFlags").ToInt32();
                                            uint   controlFlags = BitConverter.ToUInt32(packetData, memberOffset);
                                            controlFlags = Endian.FromNetwork(controlFlags);
                                            // Add the flush flag
                                            controlFlags |= (uint)EndFrameFlag.Flush;
                                            // Convert back to bytes and copy into the packet buffer.
                                            byte[] frameNumberBytes = BitConverter.GetBytes(Endian.ToNetwork(controlFlags));
                                            Array.Copy(frameNumberBytes, 0, packetData, memberOffset, frameNumberBytes.Length);
                                            // Recalculate the CRC as we've modified the packet.
                                            completedPacket.UpdateCrc();

                                            // Update the frame
                                            timer.Stop();
                                            FrameTime = timer.ElapsedMilliseconds * 1e-3f;
                                            timer.Reset();
                                            timer.Start();
                                            ++_currentFrame;
                                            ++_totalFrames;
                                        }
                                    }

                                    _packetQueue.Enqueue(completedPacket);
                                }
                            }
                            else
                            {
                                // TODO: Log CRC failure.
                            }
                        }
                    }
                    else
                    {
                        yield return(null);
                    }
                }

                // Disconnected.
                if (socket != null)
                {
                    socket.LingerState.Enabled = false;
                    socket.Close();
                    socket = null;
                }
                if (_connection.Connected)
                {
                    Status = NetworkThreadStatus.Disconnected;
                    _connection.Connected = false;
                }

                if (!_connection.AutoReconnect)
                {
                    break;
                }
                Status = NetworkThreadStatus.Reconnecting;
            }
        }