コード例 #1
0
        async Task Connect(string host, int port)
        {
            await ConnectAsync(host, port);

            _pump             = new FramePump(_client.GetStream());
            _outboundEndpoint = new OutboundTcpEndpoint(this, _pump);
            _inboundEndpoint  = _rpcEngine.AddEndpoint(_outboundEndpoint);
            _pumpThread       = new Thread(() =>
            {
                try
                {
                    Thread.CurrentThread.Name = $"TCP RPC Client Thread {Thread.CurrentThread.ManagedThreadId}";

                    _pump.Run();
                }
                finally
                {
                    _outboundEndpoint.Dismiss();
                    _inboundEndpoint.Dismiss();
                    _pump.Dispose();
                }
            });

            _pump.FrameReceived += _inboundEndpoint.Forward;
            _pumpThread.Start();
        }
コード例 #2
0
        public void Issue20()
        {
            RpcRequest <ArithmeticOperationRequest> rpcRequest = new RpcRequest <ArithmeticOperationRequest>();

            rpcRequest.Method = "AddTwoNumbers";

            ArithmeticOperationRequest request = new ArithmeticOperationRequest();

            request.NumA = 5;
            request.NumB = 8;

            rpcRequest.Request = request;

            var msg  = MessageBuilder.Create();
            var root = msg.BuildRoot <RpcRequest <ArithmeticOperationRequest> .WRITER>();

            rpcRequest.serialize(root);

            var mems = new MemoryStream();
            var pump = new FramePump(mems);

            pump.Send(msg.Frame);
            mems.Seek(0, SeekOrigin.Begin);

            var frame        = Framing.ReadSegments(mems);
            var deserializer = DeserializerState.CreateRoot(frame);
            var mainRequest  = new RpcRequest <ArithmeticOperationRequest> .READER(deserializer);

            var innerRequest = new ArithmeticOperationRequest.READER(mainRequest.Request);

            Console.WriteLine("Method Name: " + mainRequest.Method);
            Console.WriteLine("NumA: " + innerRequest.NumA.ToString());
            Console.WriteLine("NumB: " + innerRequest.NumB.ToString());
        }
コード例 #3
0
            public Connection(TcpRpcServer server, TcpClient client, FramePump pump, OutboundTcpEndpoint outboundEp, RpcEngine.RpcEndpoint inboundEp)
            {
                Client     = client;
                Pump       = pump;
                OutboundEp = outboundEp;
                InboundEp  = inboundEp;

                PumpRunner = new Thread(o =>
                {
                    try
                    {
                        Thread.CurrentThread.Name = $"TCP RPC Server Thread {Thread.CurrentThread.ManagedThreadId}";

                        Pump.Run();
                    }
                    finally
                    {
                        OutboundEp.Dismiss();
                        InboundEp.Dismiss();
                        Pump.Dispose();
                        lock (server._reentrancyBlocker)
                        {
                            --server.ConnectionCount;
                            server._connections.Remove(this);
                        }
                    }
                });
            }
コード例 #4
0
 public Connection(TcpRpcServer server, TcpClient client, FramePump pump, OutboundTcpEndpoint outboundEp, RpcEngine.RpcEndpoint inboundEp)
 {
     _server    = server;
     Client     = client;
     Pump       = pump;
     OutboundEp = outboundEp;
     InboundEp  = inboundEp;
 }
コード例 #5
0
            public void Start()
            {
                Pump = new FramePump(_stream);

                foreach (var tracer in _tracers)
                {
                    Pump.AttachTracer(tracer);
                }
                _tracers.Clear();

                OutboundEp          = new OutboundTcpEndpoint(_server, Pump);
                InboundEp           = _server._rpcEngine.AddEndpoint(OutboundEp);
                Pump.FrameReceived += InboundEp.Forward;

                State = ConnectionState.Active;

                PumpRunner = new Thread(o =>
                {
                    try
                    {
                        Thread.CurrentThread.Name = $"TCP RPC Server Thread {Thread.CurrentThread.ManagedThreadId}";

                        Pump.Run();
                    }
                    catch (ThreadInterruptedException)
                    {
                        Logger.LogError($"{Thread.CurrentThread.Name} interrupted at {Environment.StackTrace}");
                    }
                    finally
                    {
                        OutboundEp.Dismiss();
                        InboundEp.Dismiss();
                        Pump.Dispose();
                        Client.Dispose();
                        lock (_server._reentrancyBlocker)
                        {
                            --_server.ConnectionCount;
                            _server._connections.Remove(this);
                            State = ConnectionState.Down;
                            _server.OnConnectionChanged?.Invoke(_server, new ConnectionEventArgs(this));
                        }
                    }
                });
                PumpRunner.Start();
            }
コード例 #6
0
        void AcceptClients()
        {
            try
            {
                if (Thread.CurrentThread.Name == null)
                {
                    Thread.CurrentThread.Name = $"TCP RPC Acceptor Thread {Thread.CurrentThread.ManagedThreadId}";
                }

                while (true)
                {
                    var client           = _listener.AcceptTcpClient();
                    var pump             = new FramePump(client.GetStream());
                    var outboundEndpoint = new OutboundTcpEndpoint(this, pump);
                    var inboundEndpoint  = _rpcEngine.AddEndpoint(outboundEndpoint);
                    pump.FrameReceived += inboundEndpoint.Forward;

                    var connection = new Connection(this, client, pump, outboundEndpoint, inboundEndpoint);

                    lock (_reentrancyBlocker)
                    {
                        ++ConnectionCount;
                        _connections.Add(connection);

                        OnConnectionChanged?.Invoke(this, new ConnectionEventArgs(connection));
                        connection.Start();
                    }

                    connection.PumpRunner.Start();
                }
            }
            catch (SocketException)
            {
                // Listener was stopped. Maybe a little bit rude, but this is
                // our way of shutting down the acceptor thread.
            }
            catch (System.Exception exception)
            {
                // Any other exception might be due to some other problem.
                Logger.LogError(exception.Message);
            }
        }
コード例 #7
0
 public OutboundTcpEndpoint(TcpRpcServer server, FramePump pump)
 {
     _server = server;
     _pump   = pump;
 }
コード例 #8
0
        public void PipedFramePump()
        {
            int UnpackFrame(WireFrame frame)
            {
                int count = frame.Segments.Count;

                for (int i = 0; i < count; i++)
                {
                    Assert.AreEqual(i + 1, frame.Segments[i].Length);
                }

                return(count);
            }

            WireFrame PackFrame(int value)
            {
                var segments = new Memory <ulong> [value];

                for (int i = 0; i < value; i++)
                {
                    ulong[] a = new ulong[i + 1];
                    segments[i] = new Memory <ulong>(a);
                }

                return(new WireFrame(segments));
            }

            Thread rxRunner = null;

            using (var server = new AnonymousPipeServerStream(PipeDirection.Out, HandleInheritability.None))
                using (var client = new AnonymousPipeClientStream(PipeDirection.In, server.ClientSafePipeHandle))
                    using (var bc = new BlockingCollection <int>(8))
                    {
                        server.ReadMode = PipeTransmissionMode.Byte;
                        client.ReadMode = PipeTransmissionMode.Byte;

                        using (var txPump = new FramePump(server))
                            using (var rxPump = new FramePump(client))
                            {
                                rxRunner = new Thread(() =>
                                {
                                    rxPump.Run();
                                });

                                rxPump.FrameReceived += f => bc.Add(UnpackFrame(f));

                                rxRunner.Start();

                                for (int i = 0; i < 100; i++)
                                {
                                    txPump.Send(PackFrame(1));
                                    txPump.Send(PackFrame(8));
                                    txPump.Send(PackFrame(2));
                                    txPump.Send(PackFrame(7));
                                    txPump.Send(PackFrame(3));
                                    txPump.Send(PackFrame(6));
                                    txPump.Send(PackFrame(4));
                                    txPump.Send(PackFrame(5));

                                    Assert.IsTrue(SpinWait.SpinUntil(() => bc.Count == 8, 500));

                                    Assert.AreEqual(1, bc.Take());
                                    Assert.AreEqual(8, bc.Take());
                                    Assert.AreEqual(2, bc.Take());
                                    Assert.AreEqual(7, bc.Take());
                                    Assert.AreEqual(3, bc.Take());
                                    Assert.AreEqual(6, bc.Take());
                                    Assert.AreEqual(4, bc.Take());
                                    Assert.AreEqual(5, bc.Take());
                                }
                            }
                    }

            Assert.IsTrue(rxRunner.Join(500));
        }
コード例 #9
0
        public void FramePumpDeferredProcessing()
        {
            int UnpackAndVerifyFrame(WireFrame frame, int expectedCount)
            {
                int count = frame.Segments.Count;

                Assert.AreEqual(expectedCount, count);

                for (int i = 0; i < count; i++)
                {
                    int length = frame.Segments[i].Length;
                    Assert.AreEqual(expectedCount - i, length);
                    for (int j = 0; j < length; j++)
                    {
                        Assert.AreEqual((ulong)(length - j), frame.Segments[i].Span[j]);
                    }
                }

                return(count);
            }

            WireFrame PackFrame(int value)
            {
                var segments = new Memory <ulong> [value];

                for (int i = 0; i < value; i++)
                {
                    ulong[] a = new ulong[value - i];
                    segments[i] = new Memory <ulong>(a);
                    for (int j = 0; j < a.Length; j++)
                    {
                        a[j] = (ulong)(a.Length - j);
                    }
                }

                return(new WireFrame(segments));
            }

            Thread rxRunner = null;

            using (var server = new AnonymousPipeServerStream(PipeDirection.Out, HandleInheritability.None))
                using (var client = new AnonymousPipeClientStream(PipeDirection.In, server.ClientSafePipeHandle))
                    using (var bc = new BlockingCollection <WireFrame>(8))
                    {
                        server.ReadMode = PipeTransmissionMode.Byte;
                        client.ReadMode = PipeTransmissionMode.Byte;

                        using (var txPump = new FramePump(server))
                            using (var rxPump = new FramePump(client))
                            {
                                rxRunner = new Thread(() =>
                                {
                                    rxPump.Run();
                                });

                                rxPump.FrameReceived += bc.Add;

                                rxRunner.Start();

                                txPump.Send(PackFrame(1));
                                txPump.Send(PackFrame(8));
                                txPump.Send(PackFrame(2));
                                txPump.Send(PackFrame(7));
                                txPump.Send(PackFrame(3));
                                txPump.Send(PackFrame(6));
                                txPump.Send(PackFrame(4));
                                txPump.Send(PackFrame(5));

                                Assert.IsTrue(SpinWait.SpinUntil(() => bc.Count == 8, 500));

                                UnpackAndVerifyFrame(bc.Take(), 1);
                                UnpackAndVerifyFrame(bc.Take(), 8);
                                UnpackAndVerifyFrame(bc.Take(), 2);
                                UnpackAndVerifyFrame(bc.Take(), 7);
                                UnpackAndVerifyFrame(bc.Take(), 3);
                                UnpackAndVerifyFrame(bc.Take(), 6);
                                UnpackAndVerifyFrame(bc.Take(), 4);
                                UnpackAndVerifyFrame(bc.Take(), 5);
                            }
                    }

            Assert.IsTrue(rxRunner.Join(500));
        }
コード例 #10
0
 public OutboundTcpEndpoint(TcpRpcClient client, FramePump pump)
 {
     _client = client;
     _pump   = pump;
 }
コード例 #11
0
ファイル: BmpTextureCooker.cs プロジェクト: Pursche/PurEngine
        public override bool Cook(string luaPath, LuaGlobal environment, string outputDirectory, string intermediateDirectory, out string producedFile, out string error)
        {
            error        = "";
            producedFile = "";
            string assetPath = GetAssetPath(luaPath);

            using (FileStream assetStream = new FileStream(assetPath, FileMode.Open))
            {
                using (Bitmap bmp = new Bitmap(Image.FromStream(assetStream)))
                {
                    string channelMask = Env.TryGetDefault <string>(environment, "channelMask", "RGBA");

                    // Try to get all settings from .lua file or acceptable defaults
                    CapnpGen.CapTexture texture = new CapnpGen.CapTexture();

                    texture.Header      = new CapnpGen.CapTextureHeader();
                    texture.Header.Type = CapnpGen.CapTextureType.simple; // TODO: DDS support?

                    texture.Header.Width  = (uint)bmp.Width;
                    texture.Header.Height = (uint)bmp.Height;

                    texture.Header.RChannel = GetChannel(channelMask, 0);
                    texture.Header.GChannel = GetChannel(channelMask, 1);
                    texture.Header.BChannel = GetChannel(channelMask, 2);
                    texture.Header.AChannel = GetChannel(channelMask, 3);

                    PixelFormat pixelFormat   = bmp.PixelFormat;
                    int         bytesPerPixel = GetBytesPerPixel(pixelFormat);

                    // Lock the bitmap's bits.
                    Rectangle  rect    = new Rectangle(0, 0, bmp.Width, bmp.Height);
                    BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadWrite, bmp.PixelFormat);

                    // Get the address of the first line.
                    IntPtr ptr = bmpData.Scan0;

                    // Declare an array to hold the bytes of the bitmap.
                    int    bytes      = bmp.Width * bmp.Height * bytesPerPixel;
                    byte[] byteValues = new byte[bytes];

                    // Copy the color values into the array.
                    Marshal.Copy(ptr, byteValues, 0, bytes);

                    MemoryStream memoryStream = new MemoryStream();

                    // Loop over the pixels
                    int stride = bmpData.Width;
                    for (int row = 0; row < bmpData.Height; row++)
                    {
                        for (int column = 0; column < bmpData.Width; column++)
                        {
                            int pixelIndex = ((row * stride) + column) * bytesPerPixel;

                            WriteChannel(texture.Header.RChannel, byteValues, pixelIndex, pixelFormat, memoryStream);
                            WriteChannel(texture.Header.GChannel, byteValues, pixelIndex, pixelFormat, memoryStream);
                            WriteChannel(texture.Header.BChannel, byteValues, pixelIndex, pixelFormat, memoryStream);
                            WriteChannel(texture.Header.AChannel, byteValues, pixelIndex, pixelFormat, memoryStream);
                        }
                    }

                    texture.Data = memoryStream.ToArray();

                    bmp.UnlockBits(bmpData);

                    // Create output file
                    producedFile = Path.ChangeExtension(Path.GetFileName(assetPath), ".PurTexture");
                    string outFilePath = Path.Combine(outputDirectory, "textures", producedFile);
                    Directory.CreateDirectory(Path.GetDirectoryName(outFilePath));
                    using (FileStream outStream = new FileStream(outFilePath, FileMode.Create))
                    {
                        MessageBuilder message = MessageBuilder.Create();
                        var            root    = message.BuildRoot <CapnpGen.CapTexture.WRITER>();
                        texture.serialize(root);

                        var pump = new FramePump(outStream);
                        pump.Send(message.Frame);
                    }
                }
            }


            return(true);
        }
コード例 #12
0
 public OutboundTcpEndpoint(FramePump pump)
 {
     _pump = pump;
 }
コード例 #13
0
ファイル: MaterialCooker.cs プロジェクト: Pursche/PurEngine
        public override bool Cook(string luaPath, LuaGlobal environment, string outputDirectory, string intermediateDirectory, out string producedFile, out string error)
        {
            error        = "";
            producedFile = "";

            outputDirectory = Path.Combine(outputDirectory, "materials");
            Directory.CreateDirectory(outputDirectory);

            // Load XML document
            string      materialPath = GetMaterialPath(luaPath, environment);
            XmlDocument xmlDoc       = new XmlDocument();

            try
            {
                xmlDoc.Load(materialPath);
            }
            catch (Exception e)
            {
                error = e.Message;
                return(false);
            }


            // Get the root node
            XmlNode materialFileNode = xmlDoc.SelectSingleNode("//MaterialFile");

            if (materialFileNode == null)
            {
                error = "Material file does not have a root node called MaterialFile";
                return(false);
            }

            // Parse all samplers
            List <CapnpGen.CapSampler> samplers = new List <CapnpGen.CapSampler>();
            XmlNodeList samplerNodes            = materialFileNode.SelectNodes("Sampler");

            foreach (XmlNode samplerNode in samplerNodes)
            {
                if (!MaterialParser.ParseSampler(samplerNode, samplers, out error))
                {
                    return(false);
                }
            }

            // Parse all blenders
            List <CapnpGen.CapBlender> blenders = new List <CapnpGen.CapBlender>();
            XmlNodeList blenderNodes            = materialFileNode.SelectNodes("Blender");

            foreach (XmlNode blenderNode in blenderNodes)
            {
                if (!MaterialParser.ParseBlender(blenderNode, blenders, out error))
                {
                    return(false);
                }
            }

            // Parse all materials
            List <CapnpGen.CapMaterial> materials = new List <CapnpGen.CapMaterial>();
            XmlNodeList materialNodes             = materialFileNode.SelectNodes("Material");

            foreach (XmlNode materialNode in materialNodes)
            {
                if (!MaterialParser.ParseMaterial(materialNode, materials, blenders, samplers, out error))
                {
                    return(false);
                }
            }

            // Parse all material instances
            List <CapnpGen.CapMaterialInstance> materialInstances = new List <CapnpGen.CapMaterialInstance>();
            XmlNodeList materialInstanceNodes = materialFileNode.SelectNodes("MaterialInstance");

            foreach (XmlNode materialInstanceNode in materialInstanceNodes)
            {
                if (!MaterialParser.ParseMaterialInstance(materialInstanceNode, materialInstances, materials, materialPath, out error))
                {
                    return(false);
                }
            }

            // Compile all materials
            foreach (CapnpGen.CapMaterial material in materials)
            {
                if (!MaterialCompiler.CompileMaterial(material, outputDirectory, out error))
                {
                    return(false);
                }
            }

            // Serialize and save the all material instance headers
            foreach (CapnpGen.CapMaterialInstance materialInstance in materialInstances)
            {
                string headerPath = Path.Combine(outputDirectory, materialInstance.Header.Name + ".material");
                Directory.CreateDirectory(Path.GetDirectoryName(headerPath));
                using (FileStream outStream = new FileStream(headerPath, FileMode.Create))
                {
                    MessageBuilder message = MessageBuilder.Create();
                    var            root    = message.BuildRoot <CapnpGen.CapMaterialInstanceHeader.WRITER>();
                    materialInstance.Header.serialize(root);

                    var pump = new FramePump(outStream);
                    pump.Send(message.Frame);
                }

                // Copy all textures used by the material instance into the Data/material folder
                foreach (CapnpGen.CapMaterialTexture texture in materialInstance.Header.Textures)
                {
                    string destPath = Path.Combine(outputDirectory, texture.Path);
                    Directory.CreateDirectory(Path.GetDirectoryName(destPath));
                    File.Copy(texture.ContentPath, destPath, true);
                }
            }



            return(true);
        }
コード例 #14
0
ファイル: ObjModelCooker.cs プロジェクト: Pursche/PurEngine
        public override bool Cook(string luaPath, LuaGlobal environment, string outputDirectory, string intermediateDirectory, out string producedFile, out string error)
        {
            error        = "";
            producedFile = "";
            string assetPath = GetAssetPath(luaPath);

            materialStreamProvider.SetAssetPath(assetPath);

            using (FileStream assetStream = new FileStream(assetPath, FileMode.Open))
            {
                LoadResult result = objLoader.Load(assetStream);

                CapnpGen.CapModel model = new CapnpGen.CapModel();

                // Get all vertex positions
                List <CapnpGen.CapVector3> vertexPositions = new List <CapnpGen.CapVector3>();
                foreach (Vertex vertex in result.Vertices)
                {
                    CapnpGen.CapVector3 pos = new CapnpGen.CapVector3();
                    pos.X = vertex.X;
                    pos.Y = vertex.Y;
                    pos.Z = vertex.Z;

                    vertexPositions.Add(pos);
                }
                //model.VertexPositions = vertexPositions;

                // Get all vertex texCoords
                List <CapnpGen.CapVector2> vertexTexCoords = new List <CapnpGen.CapVector2>();
                foreach (Texture texture in result.Textures)
                {
                    CapnpGen.CapVector2 texCoord = new CapnpGen.CapVector2();
                    texCoord.X = texture.X;
                    texCoord.Y = texture.Y;

                    vertexTexCoords.Add(texCoord);
                }

                // Get all vertex normals
                List <CapnpGen.CapVector3> vertexNormals = new List <CapnpGen.CapVector3>();
                foreach (Normal normal in result.Normals)
                {
                    CapnpGen.CapVector3 vertexNormal = new CapnpGen.CapVector3();
                    vertexNormal.X = normal.X;
                    vertexNormal.Y = normal.Y;
                    vertexNormal.Z = normal.Z;

                    vertexNormals.Add(vertexNormal);
                }

                // Because .obj stores vertex positions, vertex texcoords and vertex normals separately and without duplication we need to "unpack" combined vertices from this data
                // Each .obj model has a list of "groups" which represent submeshes
                // Each group has a list of faces which represent quads, they have 3-4 "indices" that point to vertex positions, vertex texcoords and vertex normals separately
                // We need to iterate over these, and then build one combined vertex for each unique combination of position, texcoord and normal

                // Convert indices

                // This dictionary will hold unique vertices as keys, and it's corresponding index as value, this makes it easy for us to look up indices of duplicated vertices
                Dictionary <CapnpGen.CapVertex, UInt32> combinedVertices = new Dictionary <CapnpGen.CapVertex, uint>();

                List <UInt32> indices = new List <UInt32>();
                foreach (ObjLoader.Loader.Data.Elements.Group group in result.Groups) // A group represents a "submesh"
                {
                    foreach (Face face in group.Faces)
                    {
                        UInt32[] combinedIndices = new UInt32[face.Count];

                        for (int i = 0; i < face.Count; i++)
                        {
                            CapnpGen.CapVector3 position = vertexPositions[face[i].VertexIndex - 1];

                            int normalIndex            = face[i].NormalIndex;
                            CapnpGen.CapVector3 normal = new CapnpGen.CapVector3();
                            normal.Y = 1;
                            if (normalIndex > 0)
                            {
                                normal = vertexNormals[normalIndex - 1];
                            }

                            int texCoordIndex = face[i].TextureIndex;

                            CapnpGen.CapVector2 texCoord = new CapnpGen.CapVector2();

                            if (texCoordIndex > 0)
                            {
                                texCoord = vertexTexCoords[texCoordIndex - 1];
                            }

                            combinedIndices[i] = CombineVertex(position, normal, texCoord, ref combinedVertices);
                        }

                        if (face.Count == 4)
                        {
                            // We split the face (quad) into two triangles, the first one with index 0 1 and 2
                            indices.Add(combinedIndices[0]);
                            indices.Add(combinedIndices[1]);
                            indices.Add(combinedIndices[2]);

                            // The second one with index 2 3 and 0
                            indices.Add(combinedIndices[2]);
                            indices.Add(combinedIndices[3]);
                            indices.Add(combinedIndices[0]);
                        }
                        else if (face.Count == 3)
                        {
                            // This kind of face only has one triangle, so it's simple
                            indices.Add(combinedIndices[0]);
                            indices.Add(combinedIndices[1]);
                            indices.Add(combinedIndices[2]);
                        }
                        else
                        {
                            Debug.Assert(false); // I haven't seen a model where faces don't have 4 or 3 indices yet
                        }
                    }
                }

                CapnpGen.CapVertex[] vertices = new CapnpGen.CapVertex[combinedVertices.Count];
                combinedVertices.Keys.CopyTo(vertices, 0);
                model.Vertices = vertices;
                model.Indices  = indices;

                // Create output file
                string outputFileName = Path.ChangeExtension(Path.GetFileName(assetPath), ".model");
                producedFile = Path.Combine(outputDirectory, "models", outputFileName);
                Directory.CreateDirectory(Path.GetDirectoryName(producedFile));
                using (FileStream outStream = new FileStream(producedFile, FileMode.Create))
                {
                    MessageBuilder message = MessageBuilder.Create();
                    var            root    = message.BuildRoot <CapnpGen.CapModel.WRITER>();
                    model.serialize(root);

                    var pump = new FramePump(outStream);
                    pump.Send(message.Frame);
                }
            }

            return(true);
        }