예제 #1
0
        public XrcServer(CompositorBehavior behavior)
        {
            Listener = TcpListener.Create(31337);
            Listener.Start();
            var broadcastTimer = new Timer {
                AutoReset = true, Interval = 100
            };
            var broadcastClient = new UdpClient {
                EnableBroadcast = true
            };
            var ep        = new IPEndPoint(IPAddress.Broadcast, 31337);
            var nameBytes = Encoding.UTF8.GetBytes("My XrCompositor");
            var packet    = new byte[6 + nameBytes.Length];

            Array.Copy(BitConverter.GetBytes((ushort)31337), 0, packet, 0, 2);
            Array.Copy(BitConverter.GetBytes((uint)nameBytes.Length), 0, packet, 2, 4);
            Array.Copy(nameBytes, 0, packet, 6, nameBytes.Length);
            broadcastTimer.Elapsed += (_, __) => {
                if (!Alive)
                {
                    broadcastTimer.Stop();
                }
                else
                {
                    broadcastClient.Send(packet, packet.Length, ep);
                }
            };
            broadcastTimer.Start();
            new Thread(() => {
                while (Alive)
                {
                    if (Listener.Pending())
                    {
                        Clients.Add(new XrcClient(Listener.AcceptSocket(), behavior));
                    }
                    else
                    {
                        Thread.Sleep(50);
                    }
                }
            }).Start();
        }
예제 #2
0
 public UnityCompositor(CompositorBehavior behavior) => Behavior = behavior;
예제 #3
0
        public XrcClient(Socket socket, CompositorBehavior behavior)
        {
            Socket   = socket;
            Behavior = behavior;
            var pingCount = 0;
            var pingTimer = new Timer {
                AutoReset = true, Interval = 5000
            };

            pingTimer.Elapsed += (_, __) => {
                lock (this) {
                    if (pingCount >= 12 || !Alive)
                    {
                        // Client timed out
                        Alive = false;
                        pingTimer.Stop();
                        return;
                    }
                    pingCount++;
                    Send(1);
                }
            };
            pingTimer.Start();

            new Thread(() => {
                var minibuf = new byte[128];
                while (Alive)
                {
                    try {
                        var off = 0;
                        while (off < 8)
                        {
                            off += socket.Receive(minibuf, off, 8 - off, SocketFlags.None);
                        }
                        var len = BitConverter.ToInt32(minibuf, 0);
                        Debug.Assert(len >= 0);
                        var opcode = BitConverter.ToUInt32(minibuf, 4);
                        Behavior.Log($"Got message with opcode {opcode} and length {len}");
                        byte[] data = null;
                        if (len > 128)
                        {
                            data = new byte[len];
                        }
                        else if (len > 0)
                        {
                            data = minibuf;
                        }
                        if (data != null)
                        {
                            off = 0;
                            while (off < len)
                            {
                                off += socket.Receive(data, off, len - off, SocketFlags.None);
                            }
                        }

                        // Reset ping timer
                        pingTimer.Stop();
                        pingTimer.Start();

                        switch (opcode)
                        {
                        case 1:                                 // Ping
                            Send(2);
                            break;

                        case 2:                                 // Pong
                            pingCount--;
                            break;

                        case 1001: {                                 // Run script
                            Behavior.Log("Attempting to run script...");
                            var code = Encoding.UTF8.GetString(data, 0, len);
                            Behavior.Log($"Running script: {code.ToPrettyString()}");
                            Behavior.JobQueue.Enqueue(() => Behavior.RunScriptCode(code));
                            break;
                        }

                        case 1002: {                                 // Load script
                            var fnlen = BitConverter.ToInt32(data, 0);
                            var fn    = Encoding.UTF8.GetString(data, 4, fnlen);
                            Behavior.JobQueue.Enqueue(() => {
                                    var path = Path.Combine(Application.persistentDataPath, fn);
                                    Behavior.Log($"Writing script to {path.ToPrettyString()}");
                                    try {
                                        File.Delete(path);
                                    } catch (Exception) { }

                                    using (var fp = File.OpenWrite(path))
                                        fp.Write(data, 4 + fnlen, len - 4 - fnlen);
                                    Behavior.LoadScript(path);
                                });
                            break;
                        }

                        case 1004:                                 // Request logs
                            Behavior.LogMessage += (isError, message) =>
                                                   Send(2001,
                                                        new[] { (byte)(isError ? 1 : 0) }.Concat(Encoding.UTF8.GetBytes(message))
                                                        .ToArray());
                            break;

                        default:
                            Behavior.Log($"Got message with unknown opcode {opcode} and length {len}");
                            break;
                        }
                    } catch (Exception e) {
                        Alive = false;
                        Behavior.Log(e.ToString());
                        break;
                    }
                }
            }).Start();
        }