static void ValidateClient(TcpClient socket, Shape reference, ServerInfoMessage serverInfo, CreateShapeFunction createShape, ShapeValidationFunction validate, uint timeoutSec = 10u)
        {
            Stopwatch                    timer          = new Stopwatch();
            ServerInfoMessage            readServerInfo = new ServerInfoMessage();
            Dictionary <ulong, Resource> resources      = new Dictionary <ulong, Resource>();
            PacketBuffer                 packetBuffer   = new PacketBuffer(64 * 1024);
            Shape shape          = createShape();
            bool  endMsgReceived = false;
            bool  serverInfoRead = false;
            bool  shapeMsgRead   = false;

            timer.Start();

            // Keep looping until we get a CIdEnd ControlMessage or timeoutSec elapses.
            // Timeout ignored when debugger is attached.
            while (!endMsgReceived && (Debugger.IsAttached || timer.ElapsedMilliseconds / 1000u < timeoutSec))
            {
                if (socket.Available <= 0)
                {
                    Thread.Yield();
                    continue;
                }

                // 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)
                {
                    Assert.True(crcOk);
                    if (crcOk)
                    {
                        if (packetBuffer.DroppedByteCount != 0)
                        {
                            Console.Error.WriteLine("Dropped {0} bad bytes", packetBuffer.DroppedByteCount);
                            packetBuffer.DroppedByteCount = 0;
                        }

                        Assert.Equal(PacketHeader.PacketMarker, completedPacket.Header.Marker);
                        Assert.Equal(PacketHeader.PacketVersionMajor, completedPacket.Header.VersionMajor);
                        Assert.Equal(PacketHeader.PacketVersionMinor, completedPacket.Header.VersionMinor);

                        NetworkReader packetReader = new NetworkReader(completedPacket.CreateReadStream(true));

                        switch (completedPacket.Header.RoutingID)
                        {
                        case (int)RoutingID.ServerInfo:
                            serverInfoRead = true;
                            Assert.True(readServerInfo.Read(packetReader));

                            // Validate server info.
                            Assert.Equal(serverInfo.TimeUnit, readServerInfo.TimeUnit);
                            Assert.Equal(serverInfo.DefaultFrameTime, readServerInfo.DefaultFrameTime);
                            Assert.Equal(serverInfo.CoordinateFrame, readServerInfo.CoordinateFrame);

                            unsafe
                            {
                                for (int i = 0; i < ServerInfoMessage.ReservedBytes; ++i)
                                {
                                    Assert.Equal(serverInfo.Reserved[i], readServerInfo.Reserved[i]);
                                }
                            }
                            break;

                        case (int)RoutingID.Control:
                        {
                            // Only interested in the CIdEnd message to mark the end of the stream.
                            ControlMessage msg = new ControlMessage();
                            Assert.True(msg.Read(packetReader));

                            if (completedPacket.Header.MessageID == (int)ControlMessageID.End)
                            {
                                endMsgReceived = true;
                            }
                            break;
                        }

                        case (int)RoutingID.Mesh:
                            HandleMeshMessage(completedPacket, packetReader, resources);
                            break;

                        default:
                            if (completedPacket.Header.RoutingID == reference.RoutingID)
                            {
                                shapeMsgRead = true;
                                HandleShapeMessage(completedPacket, packetReader, shape, reference);
                            }
                            break;
                        }
                    }
                }
                // else fail?
            }

            Assert.True(serverInfoRead);
            Assert.True(shapeMsgRead);
            Assert.True(endMsgReceived);

            // Validate the shape state.
            if (shapeMsgRead)
            {
                validate(shape, reference, resources);
            }
        }
示例#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;
            }
        }