private SimpleSocket CreateSocketContext()
        {
            var socketContext = new SimpleSocket();
            socketContext.Connected = (clientSocketContext) =>
            {
                Task.Run(async () =>
                {
                    try
                    {

                        // Register service server
                        await socketContext.WriteStream.WriteInt16Async((short)RouterMessage.ServiceProvideServer);
                        await socketContext.WriteStream.WriteStringAsync(serverUrl);
                        await socketContext.WriteStream.FlushAsync();

                        while (true)
                        {
                            var routerMessage = (RouterMessage)await socketContext.ReadStream.ReadInt16Async();

                            switch (routerMessage)
                            {
                                case RouterMessage.ServiceRequestServer:
                                {
                                    var requestedUrl = await clientSocketContext.ReadStream.ReadStringAsync();
                                    var guid = await clientSocketContext.ReadStream.ReadGuidAsync();

                                    // Spawn actual server
                                    var realServerSocketContext = new SimpleSocket();
                                    realServerSocketContext.Connected = async (clientSocketContext2) =>
                                    {
                                        // Write connection string
                                        await clientSocketContext2.WriteStream.WriteInt16Async((short)RouterMessage.ServerStarted);
                                        await clientSocketContext2.WriteStream.WriteGuidAsync(guid);

                                        // Delegate next steps to actual server
                                        HandleClient(clientSocketContext2, requestedUrl);
                                    };

                                    // Start connection
                                    await realServerSocketContext.StartClient(address, port);
                                    break;
                                }
                                default:
                                    Console.WriteLine("Router: Unknown message: {0}", routerMessage);
                                    throw new ArgumentOutOfRangeException();
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        // TODO: Ideally, separate socket-related error messages (disconnection) from real errors
                        // Unfortunately, it seems WinRT returns Exception, so it seems we can't filter with SocketException/IOException only?
                        Log.Info("Client {0}:{1} disconnected with exception: {2}", clientSocketContext.RemoteAddress, clientSocketContext.RemotePort, e.Message);
                        clientSocketContext.Dispose();
                    }
                });
            };

            return socketContext;
        }
Example #2
0
        /// <summary>
        /// Initiates a connection to the router.
        /// </summary>
        /// <returns></returns>
        private static Task<SimpleSocket> InitiateConnectionToRouter()
        {
            // Let's make sure this run in a different thread (in case some operation are blocking)
            return Task.Factory.StartNew(() =>
            {
                var socketContextTCS = new TaskCompletionSource<SimpleSocket>();
                var socketContext = new SimpleSocket();
                socketContext.Connected = context =>
                {
                    socketContextTCS.TrySetResult(context);
                };

                try
                {
                    // If connecting as a client, try once, otherwise try to listen multiple time (in case port is shared)
                    switch (ConnectionMode)
                    {
                        case RouterConnectionMode.Connect:
                            socketContext.StartClient("127.0.0.1", DefaultPort).Wait();
                            break;
                        case RouterConnectionMode.Listen:
                            socketContext.StartServer(DefaultListenPort, true, 10).Wait();
                            break;
                        case RouterConnectionMode.ConnectThenListen:
                            bool clientException = false;
                            try
                            {
                                socketContext.StartClient("127.0.0.1", DefaultPort).Wait();
                            }
                            catch (Exception) // Ideally we should filter SocketException, but not available on some platforms (maybe it should be wrapped in a type available on all paltforms?)
                            {
                                clientException = true;
                            }
                            if (clientException)
                            {
                                socketContext.StartServer(DefaultListenPort, true, 10).Wait();
                            }
                            break;
                        default:
                            throw new ArgumentOutOfRangeException();
                    }

                    // Connection should happen within 5 seconds, otherwise consider there is no connection router trying to connect back to us
                    if (!socketContextTCS.Task.Wait(TimeSpan.FromSeconds(5)))
                        throw new InvalidOperationException("Connection router did not connect back to our listen socket");

                    return socketContextTCS.Task.Result;
                }
                catch (Exception e)
                {
                    Log.Error("Could not connect to connection router using mode {0}: {1}", ConnectionMode, e.Message);
                    throw;
                }
            },
                CancellationToken.None,
                TaskCreationOptions.LongRunning,
                TaskScheduler.Default);
        }
Example #3
0
        private SimpleSocket CreateSocketContext()
        {
            var socketContext = new SimpleSocket();
            socketContext.Connected = (clientSocketContext) =>
            {
                Task.Run(async () =>
                {
                    try
                    {
                        // Routing
                        var routerMessage = (RouterMessage)await clientSocketContext.ReadStream.ReadInt16Async();

                        Log.Info("Client {0}:{1} connected, with message {2}", clientSocketContext.RemoteAddress, clientSocketContext.RemotePort, routerMessage);

                        switch (routerMessage)
                        {
                            case RouterMessage.TaskProvideServer:
                            {
                                await HandleMessageServiceProvideServer(clientSocketContext, true);
                                break;
                            }
                            case RouterMessage.ServiceProvideServer:
                            {
                                await HandleMessageServiceProvideServer(clientSocketContext, false);
                                break;
                            }
                            case RouterMessage.ServerStarted:
                            {
                                await HandleMessageServerStarted(clientSocketContext);
                                break;
                            }
                            case RouterMessage.ClientRequestServer:
                            {
                                await HandleMessageClientRequestServer(clientSocketContext);
                                break;
                            }
                            default:
                                throw new ArgumentOutOfRangeException(string.Format("Router: Unknown message: {0}", routerMessage));
                        }
                    }
                    catch (Exception e)
                    {
                        // TODO: Ideally, separate socket-related error messages (disconnection) from real errors
                        // Unfortunately, it seems WinRT returns Exception, so it seems we can't filter with SocketException/IOException only?
                        Log.Info("Client {0}:{1} disconnected with exception: {2}", clientSocketContext.RemoteAddress, clientSocketContext.RemotePort, e.Message);
                        clientSocketContext.Dispose();
                    }
                });
            };

            return socketContext;
        }
Example #4
0
        public async Task StartServer(int port, bool singleConnection, int retryCount = 1)
        {
            // Create TCP listener
            var listener = new TcpSocketListener(2048);

            listener.ConnectionReceived = async (sender, args) =>
            {
                var clientSocketContext = new SimpleSocket();

                try
                {
                    // Stop listening if we accept only a single connection
                    if (singleConnection)
                        await listener.StopListeningAsync();

                    clientSocketContext.SetSocket((TcpSocketClient)args.SocketClient);

                    // Do an ack with magic packet (necessary so that we know it's not a dead connection,
                    // it sometimes happen when doing port forwarding because service don't refuse connection right away but only fails when sending data)
                    await SendAndReceiveAck(clientSocketContext.socket, MagicAck, MagicAck);

                    if (Connected != null)
                        Connected(clientSocketContext);

                    clientSocketContext.isConnected = true;
                }
                catch (Exception)
                {
                    clientSocketContext.DisposeSocket();
                }
            };

            for (int i = 0; i < retryCount; ++i)
            {
                try
                {
                    // Start listening
                    await listener.StartListeningAsync(port);
                    break; // Break if no exception, otherwise retry
                }
                catch (Exception)
                {
                    // If there was an exception last try, propragate exception
                    if (i == retryCount - 1)
                        throw;
                }
            }
        }
Example #5
0
        private void RunTests()
        {
            AppDomain.CurrentDomain.UnhandledException += (a, e) =>
            {
                var exception = e.ExceptionObject as Exception;
                if (exception != null)
                {
                    var exceptionText = exception.ToString();
                    stringBuilder.Append($"Tests fatal failure: {exceptionText}");
                    Logger.Debug($"Unhandled fatal exception: {exception.ToString()}");
                    EndTesting(true);
                }
            };

            var xenkoVersion = Intent.GetStringExtra(TestRunner.XenkoVersion);
            var buildNumber = Parse(Intent.GetStringExtra(TestRunner.XenkoBuildNumber) ?? "-1");
            var branchName = Intent.GetStringExtra(TestRunner.XenkoBranchName) ?? "";

            // Remove extra (if activity is recreated)
            Intent.RemoveExtra(TestRunner.XenkoVersion);
            Intent.RemoveExtra(TestRunner.XenkoBuildNumber);
            Intent.RemoveExtra(TestRunner.XenkoBranchName);

            Logger.Info(@"*******************************************************************************************************************************");
            Logger.Info(@"date: " + DateTime.Now);
            Logger.Info(@"*******************************************************************************************************************************");

            // Connect to server right away to let it know we're alive
            //var client = Connect(serverAddresses, serverPort);

            var url = "/task/SiliconStudio.Xenko.TestRunner.exe";

            socketContext = RouterClient.RequestServer(url).Result;
            socketBinaryWriter = new BinaryWriter(socketContext.WriteStream);

            // Update build number (if available)
            ImageTester.ImageTestResultConnection.BuildNumber = buildNumber;
            ImageTester.ImageTestResultConnection.BranchName = branchName ?? "";
            
            // Connect beforehand to image tester, so that first test timing is not affected by initial connection
            try
            {
                ImageTester.Connect();
            }
            catch (Exception e)
            {
                Logger.Error("Error connecting to image tester server: {0}", e);
            }

            // Start unit test
            var cachePath = CacheDir.AbsolutePath;
            var timeNow = DateTime.Now;

            // Generate result file name
            resultFile = Path.Combine(cachePath, $"TestResult-{timeNow:yyyy-MM-dd_hh-mm-ss-tt}.xml");

            Logger.Debug(@"Execute tests");

            stringBuilder = new StringBuilder();
            var stringWriter = new StringWriter(stringBuilder);

            try
            {
                new TextUI(stringWriter)
                {
                    TestListener = this
                }.Execute(new[] { "-format:nunit2", $"-result:{resultFile}" });
            }
            catch (Exception ex)
            {
                stringBuilder.Append($"Tests fatal failure: {ex}");
                Logger.Error($"Tests fatal failure: {ex}");
            }           

            EndTesting(false);
        }
Example #6
0
 public Service(SimpleSocket socket)
 {
     Socket = socket;
 }
Example #7
0
        /// <summary>
        /// Initiates a connection to the router.
        /// </summary>
        /// <returns></returns>
        private static Task <SimpleSocket> InitiateConnectionToRouter()
        {
            // Let's make sure this run in a different thread (in case some operation are blocking)
            return(Task.Factory.StartNew(() =>
            {
                var socketContextTCS = new TaskCompletionSource <SimpleSocket>();
                var socketContext = new SimpleSocket();
                socketContext.Connected = context =>
                {
                    socketContextTCS.TrySetResult(context);
                };

                try
                {
                    // If connecting as a client, try once, otherwise try to listen multiple time (in case port is shared)
                    switch (ConnectionMode)
                    {
                    case RouterConnectionMode.Connect:
                        socketContext.StartClient("127.0.0.1", DefaultPort).Wait();
                        break;

                    case RouterConnectionMode.Listen:
                        socketContext.StartServer(DefaultListenPort, true, 10).Wait();
                        break;

                    case RouterConnectionMode.ConnectThenListen:
                        bool clientException = false;
                        try
                        {
                            socketContext.StartClient("127.0.0.1", DefaultPort).Wait();
                        }
                        catch (Exception)     // Ideally we should filter SocketException, but not available on some platforms (maybe it should be wrapped in a type available on all paltforms?)
                        {
                            clientException = true;
                        }
                        if (clientException)
                        {
                            socketContext.StartServer(DefaultListenPort, true, 10).Wait();
                        }
                        break;

                    default:
                        throw new ArgumentOutOfRangeException();
                    }

                    // Connection should happen within 10 seconds, otherwise consider there is no connection router trying to connect back to us
                    if (!socketContextTCS.Task.Wait(TimeSpan.FromSeconds(10)))
                    {
                        throw new SimpleSocketException("Connection router did not connect back to our listen socket");
                    }

                    return socketContextTCS.Task.Result;
                }
                catch (Exception e)
                {
                    Log.Error("Could not connect to connection router using mode {0}: {1}", ConnectionMode, e.Message);
                    throw;
                }
            },
                                         CancellationToken.None,
                                         TaskCreationOptions.LongRunning,
                                         TaskScheduler.Default));
        }
Example #8
0
        protected override async void HandleClient(SimpleSocket clientSocket, string url)
        {
            clientResultsEvent.Set();

            await AcceptConnection(clientSocket);

            try
            {
                var binaryReader = new BinaryReader(clientSocket.ReadStream);

                //Read events
                TestRunnerMessageType messageType;
                do
                {
                    messageType = (TestRunnerMessageType)binaryReader.ReadInt32();
                    switch (messageType)
                    {
                        case TestRunnerMessageType.TestStarted:
                        {
                            var testFullName = binaryReader.ReadString();
                            Console.WriteLine($"Test Started: {testFullName}");
                            clientResultsEvent.Set();
                            break;
                        }
                        case TestRunnerMessageType.TestFinished:
                        {
                            var testFullName = binaryReader.ReadString();
                            var status = binaryReader.ReadString();
                            Console.WriteLine($"Test {status}: {testFullName}");
                            clientResultsEvent.Set();
                            break;
                        }
                        case TestRunnerMessageType.TestOutput:
                        {
                            var outputType = binaryReader.ReadString();
                            var outputText = binaryReader.ReadString();
                            Console.WriteLine($"  {outputType}: {outputText}");
                            clientResultsEvent.Set();
                            break;
                        }
                        case TestRunnerMessageType.SessionSuccess:
                            testFailed = false;
                            break;
                        case TestRunnerMessageType.SessionFailure:
                            testFailed = true;
                            break;
                        default:
                            throw new ArgumentOutOfRangeException();
                    }
                } while (messageType != TestRunnerMessageType.SessionFailure && messageType != TestRunnerMessageType.SessionSuccess);

                // Mark test session as finished
                testFinished = true;

                //Read output
                var output = binaryReader.ReadString();
                Console.WriteLine(output);

                // Read XML result
                var result = binaryReader.ReadString();
                Console.WriteLine(result);

                // Write XML result to disk
                File.WriteAllText(resultFile, result);

                clientResultsEvent.Set();
            }
            catch (Exception)
            {
                clientResultsEvent.Set();
                Console.WriteLine(@"Client disconnected before sending results, a fatal crash might have occurred.");
            }
        }
 /// <summary>
 /// Let router knows that we want to continue with that connection.
 /// </summary>
 /// <param name="clientSocket">The client socket.</param>
 /// <returns></returns>
 protected async Task AcceptConnection(SimpleSocket clientSocket)
 {
     await clientSocket.WriteStream.WriteInt32Async(0); // error code OK
     await clientSocket.WriteStream.FlushAsync();
 }
 /// <summary>
 /// Let router knows we refuse the connection, and why.
 /// </summary>
 /// <param name="clientSocket">The client socket.</param>
 /// <param name="errorCode">The error code.</param>
 /// <param name="errorMessage">The error message.</param>
 /// <returns></returns>
 protected async Task RefuseConnection(SimpleSocket clientSocket, int errorCode, string errorMessage)
 {
     await clientSocket.WriteStream.WriteInt32Async(errorCode);
     await clientSocket.WriteStream.WriteStringAsync(errorMessage);
     await clientSocket.WriteStream.FlushAsync();
 }
        protected override async void HandleClient(SimpleSocket clientSocket, string url)
        {
            await AcceptConnection(clientSocket);

            var socketMessageLayer = new SocketMessageLayer(clientSocket, true);

            socketMessageLayer.AddPacketHandler<TestRegistrationRequest>(request =>
            {
                if (request.Tester)
                {
                    switch (request.Platform)
                    {
                        case (int)PlatformType.Windows:
                            {
                                Process process = null;
                                var debugInfo = "";
                                try
                                {
                                    var workingDir = Path.GetDirectoryName(request.Cmd);
                                    if (workingDir != null)
                                    {
                                        var start = new ProcessStartInfo
                                        {
                                            WorkingDirectory = workingDir,
                                            FileName = request.Cmd
                                        };
                                        start.EnvironmentVariables["SiliconStudioXenkoDir"] = Environment.GetEnvironmentVariable("SiliconStudioXenkoDir");
                                        start.UseShellExecute = false;
                                        start.RedirectStandardError = true;
                                        start.RedirectStandardOutput = true;

                                        debugInfo = "Starting process " + start.FileName + " with path " + start.WorkingDirectory;
                                        socketMessageLayer.Send(new LogRequest { Message = debugInfo }).Wait();
                                        process = Process.Start(start);
                                    }
                                }
                                catch (Exception ex)
                                {
                                    socketMessageLayer.Send(new StatusMessageRequest { Error = true, Message = "Launch exception: " + ex.Message }).Wait();
                                }

                                if (process == null)
                                {
                                    socketMessageLayer.Send(new StatusMessageRequest { Error = true, Message = "Failed to start game process. " + debugInfo }).Wait();
                                }
                                else
                                {
                                    process.OutputDataReceived += (sender, args) =>
                                    {
                                        try
                                        {
                                            socketMessageLayer.Send(new LogRequest { Message = $"STDIO: {args.Data}" }).Wait();
                                        }
                                        catch
                                        {
                                        }
                                    };

                                    process.ErrorDataReceived += (sender, args) =>
                                    {
                                        try
                                        {
                                            socketMessageLayer.Send(new LogRequest { Message = $"STDERR: {args.Data}" }).Wait();
                                        }
                                        catch
                                        {
                                        }
                                    };

                                    process.BeginOutputReadLine();
                                    process.BeginErrorReadLine();

                                    var currenTestPair = new TestPair { TesterSocket = socketMessageLayer, GameName = request.GameAssembly, Process = process };
                                    processes[request.GameAssembly] = currenTestPair;
                                    testerToGame[socketMessageLayer] = currenTestPair;
                                    socketMessageLayer.Send(new LogRequest { Message = "Process created, id: " + process.Id.ToString() }).Wait();
                                }
                                break;
                            }
                        case (int)PlatformType.Android:
                            {
                                Process process = null;
                                try
                                {
                                    process = Process.Start("cmd.exe", $"/C adb shell monkey -p {request.GameAssembly}.{request.GameAssembly} -c android.intent.category.LAUNCHER 1");
                                }
                                catch (Exception ex)
                                {
                                    socketMessageLayer.Send(new StatusMessageRequest { Error = true, Message = "Launch exception: " + ex.Message }).Wait();
                                }

                                if (process == null)
                                {
                                    socketMessageLayer.Send(new StatusMessageRequest { Error = true, Message = "Failed to start game process." }).Wait();
                                }
                                else
                                {
                                    lock (loggerLock)
                                    {
                                        currentTester = socketMessageLayer;
                                    }

                                    var currenTestPair = new TestPair
                                    {
                                        TesterSocket = socketMessageLayer,
                                        GameName = request.GameAssembly,
                                        Process = process,
                                        TestEndAction = () =>
{
                                            // force stop - only works for Android 3.0 and above.
                                            Process.Start("cmd.exe", $"/C adb shell am force-stop {request.GameAssembly}.{request.GameAssembly}");
}
                                    };
                                    processes[request.GameAssembly] = currenTestPair;
                                    testerToGame[socketMessageLayer] = currenTestPair;
                                    socketMessageLayer.Send(new LogRequest { Message = "Process created, id: " + process.Id.ToString() }).Wait();
                                }
                                break;
                            }
                        case (int)PlatformType.iOS:
                            {
                                Process process = null;
                                var debugInfo = "";
                                try
                                {
                                    Thread.Sleep(5000); //ios processes might be slow to close, we must make sure that we start clean
                                    var start = new ProcessStartInfo
                                    {
                                        WorkingDirectory = $"{Environment.GetEnvironmentVariable("SiliconStudioXenkoDir")}\\Bin\\Windows-Direct3D11\\",
                                        FileName = $"{Environment.GetEnvironmentVariable("SiliconStudioXenkoDir")}\\Bin\\Windows-Direct3D11\\idevicedebug.exe",
                                        Arguments = $"run com.your-company.{request.GameAssembly}",
                                        UseShellExecute = false
                                    };
                                    debugInfo = "Starting process " + start.FileName + " with path " + start.WorkingDirectory;
                                    process = Process.Start(start);
                                }
                                catch (Exception ex)
                                {
                                    socketMessageLayer.Send(new StatusMessageRequest { Error = true, Message = $"Launch exception: {ex.Message} info: {debugInfo}" }).Wait();
                                }

                                if (process == null)
                                {
                                    socketMessageLayer.Send(new StatusMessageRequest { Error = true, Message = "Failed to start game process. " + debugInfo }).Wait();
                                }
                                else
                                {
                                    lock (loggerLock)
                                    {
                                        currentTester = socketMessageLayer;
                                    }

                                    var currenTestPair = new TestPair { TesterSocket = socketMessageLayer, GameName = request.GameAssembly, Process = process };
                                    processes[request.GameAssembly] = currenTestPair;
                                    testerToGame[socketMessageLayer] = currenTestPair;
                                    socketMessageLayer.Send(new LogRequest { Message = "Process created, id: " + process.Id.ToString() }).Wait();
                                }
                                break;
                            }
                    }
                }
                else //Game process
                {
                    TestPair pair;
                    if (!processes.TryGetValue(request.GameAssembly, out pair)) return;

                    pair.GameSocket = socketMessageLayer;

                    testerToGame[pair.TesterSocket] = pair;
                    gameToTester[pair.GameSocket] = pair;

                    pair.TesterSocket.Send(new StatusMessageRequest { Error = false, Message = "Start" }).Wait();

                    Console.WriteLine($"Starting test {request.GameAssembly}");
                }
            });

            socketMessageLayer.AddPacketHandler<KeySimulationRequest>(request =>
            {
                var game = testerToGame[socketMessageLayer];
                game.GameSocket.Send(request).Wait();
            });

            socketMessageLayer.AddPacketHandler<TapSimulationRequest>(request =>
            {
                var game = testerToGame[socketMessageLayer];
                game.GameSocket.Send(request).Wait();
            });

            socketMessageLayer.AddPacketHandler<ScreenshotRequest>(request =>
            {
                var game = testerToGame[socketMessageLayer];
                game.GameSocket.Send(request).Wait();
            });

            socketMessageLayer.AddPacketHandler<TestEndedRequest>(request =>
            {
                var game = testerToGame[socketMessageLayer];
                game.GameSocket.Send(request).Wait();

                testerToGame.Remove(socketMessageLayer);
                gameToTester.Remove(game.GameSocket);
                processes.Remove(game.GameName);

                socketMessageLayer.Context.Dispose();
                game.GameSocket.Context.Dispose();

                game.Process.Kill();
                game.Process.Dispose();

                lock (loggerLock)
                {
                    currentTester = null;
                }

                game.TestEndAction?.Invoke();

                Console.WriteLine($"Finished test {game.GameName}");
            });

            socketMessageLayer.AddPacketHandler<TestAbortedRequest>(request =>
            {
                var game = testerToGame[socketMessageLayer];

                testerToGame.Remove(socketMessageLayer);
                processes.Remove(game.GameName);

                socketMessageLayer.Context.Dispose();

                game.Process.Kill();
                game.Process.Dispose();

                lock (loggerLock)
                {
                    currentTester = null;
                }

                game.TestEndAction?.Invoke();

                Console.WriteLine($"Aborted test {game.GameName}");
            });

            socketMessageLayer.AddPacketHandler<ScreenShotPayload>(request =>
            {
                var tester = gameToTester[socketMessageLayer];

                var imageData = new TestResultImage();
                var stream = new MemoryStream(request.Data);
                imageData.Read(new BinaryReader(stream));
                stream.Dispose();
                var resultFileStream = File.OpenWrite(request.FileName);
                imageData.Image.Save(resultFileStream, ImageFileType.Png);
                resultFileStream.Dispose();

                tester.TesterSocket.Send(new ScreenshotStored()).Wait();
            });

            Task.Run(async () =>
            {
                try
                {
                    await socketMessageLayer.MessageLoop();
                }
                catch
                {
                }
            });
        }
Example #12
0
 public SocketMessageLayer(SimpleSocket context, bool isServer)
 {
     this.context  = context;
     this.isServer = isServer;
 }
Example #13
0
        protected override async void HandleClient(SimpleSocket clientSocket, string url)
        {
            await AcceptConnection(clientSocket);

            var socketMessageLayer = new SocketMessageLayer(clientSocket, true);

            socketMessageLayer.AddPacketHandler<TestRegistrationRequest>(request =>
            {
                if (request.Tester)
                {
                    switch (request.Platform)
                    {
                        case (int)PlatformType.Windows:
                            {
                                Process process = null;
                                var debugInfo = "";
                                try
                                {
                                    var start = new ProcessStartInfo
                                    {
                                        WorkingDirectory = Path.GetDirectoryName(request.Cmd),
                                        FileName = request.Cmd,
                                    };
                                    start.EnvironmentVariables["SiliconStudioXenkoDir"] = Environment.GetEnvironmentVariable("SiliconStudioXenkoDir");
                                    start.UseShellExecute = false;

                                    debugInfo = "Starting process " + start.FileName + " with path " + start.WorkingDirectory;
                                    socketMessageLayer.Send(new LogRequest { Message = debugInfo }).Wait();
                                    process = Process.Start(start);
                                }
                                catch (Exception ex)
                                {
                                    socketMessageLayer.Send(new StatusMessageRequest { Error = true, Message = "Launch exception: " + ex.Message }).Wait();
                                }

                                if (process == null)
                                {
                                    socketMessageLayer.Send(new StatusMessageRequest { Error = true, Message = "Failed to start game process. " + debugInfo }).Wait();
                                }
                                else
                                {
                                    processes[request.GameAssembly] = new TestProcess { Process = process, TesterSocket = socketMessageLayer };
                                    socketMessageLayer.Send(new LogRequest { Message = "Process created, id: " + process.Id.ToString() }).Wait();
                                }
                                break;
                            }
                        case (int)PlatformType.Android:
                            {
                                Process process = null;                                
                                var debugInfo = "";
                                try
                                {
                                    process = Process.Start("cmd.exe", $"/C adb shell monkey -p {request.GameAssembly}.{request.GameAssembly} -c android.intent.category.LAUNCHER 1");
                                }
                                catch (Exception ex)
                                {
                                    socketMessageLayer.Send(new StatusMessageRequest { Error = true, Message = "Launch exception: " + ex.Message }).Wait();
                                }

                                if (process == null)
                                {
                                    socketMessageLayer.Send(new StatusMessageRequest { Error = true, Message = "Failed to start game process. " + debugInfo }).Wait();
                                }
                                else
                                {
                                    processes[request.GameAssembly] = new TestProcess { Process = process, TesterSocket = socketMessageLayer };
                                    socketMessageLayer.Send(new LogRequest { Message = "Process created, id: " + process.Id.ToString() }).Wait();
                                }
                                break;
                            }
                    }
                }
                else //Game process
                {
                    TestProcess process;
                    if (processes.TryGetValue(request.GameAssembly, out process))
                    {
                        process.GameSocket = socketMessageLayer;
                        testerToGame[process.TesterSocket] = process.GameSocket;
                        gameToTester[process.GameSocket] = process.TesterSocket;
                        process.TesterSocket.Send(new StatusMessageRequest { Error = false, Message = "Start" }).Wait();
                    }
                }
            });

            socketMessageLayer.AddPacketHandler<KeySimulationRequest>(request =>
            {
                var game = testerToGame[socketMessageLayer];
                game.Send(request).Wait();
            });

            socketMessageLayer.AddPacketHandler<TapSimulationRequest>(request =>
            {
                var game = testerToGame[socketMessageLayer];
                game.Send(request).Wait();
            });

            socketMessageLayer.AddPacketHandler<ScreenshotRequest>(request =>
            {
                var game = testerToGame[socketMessageLayer];
                game.Send(request).Wait();
            });

            socketMessageLayer.AddPacketHandler<TestEndedRequest>(request =>
            {
                var game = testerToGame[socketMessageLayer];
                game.Send(request).Wait();
                testerToGame.Remove(socketMessageLayer);
            });

            socketMessageLayer.AddPacketHandler<ScreenShotPayload>(request =>
            {
                var tester = gameToTester[socketMessageLayer];

                var imageData = new TestResultImage();
                var stream = new MemoryStream(request.Data);
                imageData.Read(new BinaryReader(stream));
                stream.Dispose();
                var resultFileStream = File.OpenWrite(request.FileName);
                imageData.Image.Save(resultFileStream, ImageFileType.Png);
                resultFileStream.Dispose();

                tester.Send(new ScreenshotStored()).Wait();
            });

            Task.Run(() => socketMessageLayer.MessageLoop());
        }
Example #14
0
 private async Task ForwardSocket(SimpleSocket source, SimpleSocket target)
 {
     var buffer = new byte[1024];
     while (true)
     {
         var bufferLength = await source.ReadStream.ReadAsync(buffer, 0, buffer.Length);
         if (bufferLength == 0)
             throw new IOException("Socket closed");
         await target.WriteStream.WriteAsync(buffer, 0, bufferLength);
         await target.WriteStream.FlushAsync();
     }
 }
Example #15
0
        /// <summary>
        /// Handles ServiceProvideServer messages. It allows service to publicize what "server" they can instantiate.
        /// </summary>
        /// <param name="clientSocket">The client socket context.</param>
        /// <param name="task">If it's a task the service will overwrite old instances</param>
        /// <returns></returns>
        private async Task HandleMessageServiceProvideServer(SimpleSocket clientSocket, bool task)
        {
            var url = await clientSocket.ReadStream.ReadStringAsync();

            lock (registeredServices)
            {
                TaskCompletionSource<Service> service;
                if (task)
                {
                    if (registeredServices.TryGetValue(url, out service))
                    {
                        var result = service.Task.Result;
                        result.Socket.Dispose();
                    }

                    service = new TaskCompletionSource<Service>();
                    registeredServices[url] = service;
                }
                else
                {
                    if (!registeredServices.TryGetValue(url, out service))
                    {
                        service = new TaskCompletionSource<Service>();
                        registeredServices.Add(url, service);
                    }
                }

                service.TrySetResult(new Service(clientSocket));
            }

            // TODO: Handle server disconnections
            //clientSocketContext.Disconnected += 
        }
Example #16
0
        /// <summary>
        /// Handles ServerStarted messages. It happens when service opened a new "server" connection back to us.
        /// </summary>
        /// <param name="clientSocket">The client socket context.</param>
        /// <returns></returns>
        private async Task HandleMessageServerStarted(SimpleSocket clientSocket)
        {
            var guid = await clientSocket.ReadStream.ReadGuidAsync();
            var errorCode = await clientSocket.ReadStream.ReadInt32Async();
            var errorMessage = (errorCode != 0) ? await clientSocket.ReadStream.ReadStringAsync() : null;

            // Notify any waiter that a server with given GUID is available
            TaskCompletionSource<SimpleSocket> serverSocketTCS;
            lock (pendingServers)
            {
                if (!pendingServers.TryGetValue(guid, out serverSocketTCS))
                {
                    Log.Error("Could not find a matching server Guid");
                    clientSocket.Dispose();
                    return;
                }

                pendingServers.Remove(guid);
            }

            if (errorCode != 0)
                serverSocketTCS.TrySetException(new Exception(errorMessage));
            else
                serverSocketTCS.TrySetResult(clientSocket);
        }
Example #17
0
        /// <summary>
        /// Handles ClientRequestServer messages.
        /// It will try to find a matching service (spawn it if not started yet), and ask it to establish a new "server" connection back to us.
        /// </summary>
        /// <param name="clientSocket">The client socket context.</param>
        /// <returns></returns>
        private async Task HandleMessageClientRequestServer(SimpleSocket clientSocket)
        {
            // Check for an existing server
            // TODO: Proper Url parsing (query string)
            var url = await clientSocket.ReadStream.ReadStringAsync();

            Log.Info("Client {0}:{1} sent message ClientRequestServer with URL {2}", clientSocket.RemoteAddress, clientSocket.RemotePort, url);

            string[] urlSegments;
            string urlParameters;
            RouterHelper.ParseUrl(url, out urlSegments, out urlParameters);
            if (urlSegments.Length == 0)
                throw new InvalidOperationException("No URL Segments");

            SimpleSocket serverSocket = null;
            ExceptionDispatchInfo serverSocketCapturedException = null;

            try
            {
                // For now, we handle only "service" URL
                switch (urlSegments[0])
                {
                    case "service":
                    {
                        // From the URL, start service (if not started yet) and ask it to provide a server
                        serverSocket = await SpawnServerFromService(url, false);
                        break;
                    }
                    case "task":
                    {
                        // From the URL, start service (if not started yet) and ask it to provide a server
                        serverSocket = await SpawnServerFromService(url, true);
                    }
                        break;
                    case "redirect":
                    {
                        // Redirect to a IP/port
                        serverSocket = new SimpleSocket();
                        var host = urlSegments[1];
                        var port = int.Parse(urlSegments[2]);

                        // Note: for security reasons, we currently use a whitelist
                        if (host == "XenkoBuild.siliconstudio.co.jp" && port == 1832)
                            await serverSocket.StartClient(host, port, false);
                        else
                            throw new InvalidOperationException("Trying to redirect to a non-whitelisted host/port");
                            break;
                    }
                    default:
                        throw new InvalidOperationException("This type of URL is not supported");
                }
            }
            catch (Exception e)
            {
                serverSocketCapturedException = ExceptionDispatchInfo.Capture(e);
            }


            if (serverSocketCapturedException != null)
            {
                try
                {
                    // Notify client that there was an error
                    await clientSocket.WriteStream.WriteInt16Async((short)RouterMessage.ClientServerStarted);
                    await clientSocket.WriteStream.WriteInt32Async(1); // error code Failure
                    await clientSocket.WriteStream.WriteStringAsync(serverSocketCapturedException.SourceException.Message);
                    await clientSocket.WriteStream.FlushAsync();
                }
                finally
                {
                    serverSocketCapturedException.Throw();
                }
            }

            try
            {
                // Notify client that we've found a server for it
                await clientSocket.WriteStream.WriteInt16Async((short)RouterMessage.ClientServerStarted);
                await clientSocket.WriteStream.WriteInt32Async(0); // error code OK
                await clientSocket.WriteStream.FlushAsync();

                // Let's forward clientSocketContext and serverSocketContext
                await await Task.WhenAny(
                    ForwardSocket(clientSocket, serverSocket),
                    ForwardSocket(serverSocket, clientSocket));
            }
            catch
            {
                serverSocket.Dispose();
                throw;
            }
        }
Example #18
0
        /// <inheritdoc/>
        protected override async void HandleClient(SimpleSocket clientSocket, string url)
        {
            string[] urlSegments;
            string urlParameters;
            RouterHelper.ParseUrl(url, out urlSegments, out urlParameters);
            var parameters = RouterHelper.ParseQueryString(urlParameters);
            var mode = parameters["mode"];

            // We accept everything
            await AcceptConnection(clientSocket);

            var socketMessageLayer = new SocketMessageLayer(clientSocket, true);

            Guid? packageId = null;
            {
                Guid packageIdParsed;
                if (Guid.TryParse(parameters["packageid"], out packageIdParsed))
                    packageId = packageIdParsed;
            }

            if (mode == "gamestudio")
            {
                Console.WriteLine(@"GameStudio mode started!");

                if (!packageId.HasValue)
                    return;

                lock (gameStudioPerPackageId)
                {
                    gameStudioPerPackageId[packageId.Value] = socketMessageLayer;
                }
            }
            else
            {
                // Create an effect compiler per connection
                var effectCompiler = new EffectCompiler();

                Console.WriteLine(@"Client connected");

                // TODO: This should come from an "init" packet
                effectCompiler.SourceDirectories.Add(EffectCompilerBase.DefaultSourceShaderFolder);

                // Make a VFS that will access remotely the DatabaseFileProvider
                // TODO: Is that how we really want to do that in the future?
                var networkVFS = new NetworkVirtualFileProvider(socketMessageLayer, "/asset");
                VirtualFileSystem.RegisterProvider(networkVFS);
                effectCompiler.FileProvider = networkVFS;

                socketMessageLayer.AddPacketHandler<RemoteEffectCompilerEffectRequest>(packet => ShaderCompilerRequestHandler(socketMessageLayer, effectCompiler, packet));

                socketMessageLayer.AddPacketHandler<RemoteEffectCompilerEffectRequested>(packet =>
                {
                    if (!packageId.HasValue)
                        return;

                    SocketMessageLayer gameStudio;
                    lock (gameStudioPerPackageId)
                    {
                        if (!gameStudioPerPackageId.TryGetValue(packageId.Value, out gameStudio))
                            return;
                    }

                    // Forward to game studio
                    gameStudio.Send(packet);
                });
            }

            Task.Run(() => socketMessageLayer.MessageLoop());
        }
 /// <summary>
 /// Called when a new client connection has been established.
 /// Before writing anything to the stream, HandleClient is responsible for either calling <see cref="AcceptConnection"/> or <see cref="RefuseConnection"/>.
 /// </summary>
 /// <param name="clientSocket">The client socket.</param>
 /// <param name="url">The requested URL.</param>
 protected abstract void HandleClient(SimpleSocket clientSocket, string url);
Example #20
0
 public static bool Connect(SimpleSocket simpleSocket)
 {
     ImageComparisonServer = simpleSocket.Socket;
     return OpenConnection();
 }
Example #21
0
        /// <summary>
        /// Handles ClientRequestServer messages.
        /// It will try to find a matching service (spawn it if not started yet), and ask it to establish a new "server" connection back to us.
        /// </summary>
        /// <param name="clientSocket">The client socket context.</param>
        /// <returns></returns>
        private async Task HandleMessageClientRequestServer(SimpleSocket clientSocket)
        {
            // Check for an existing server
            // TODO: Proper Url parsing (query string)
            var url = await clientSocket.ReadStream.ReadStringAsync();

            string[] urlSegments;
            string urlParameters;
            RouterHelper.ParseUrl(url, out urlSegments, out urlParameters);
            if (urlSegments.Length == 0)
                throw new InvalidOperationException("No URL Segments");

            SimpleSocket serverSocket = null;
            ExceptionDispatchInfo serverSocketCapturedException = null;

            try
            {
                // For now, we handle only "service" URL
                switch (urlSegments[0])
                {
                    case "service":
                    {
                        // From the URL, start service (if not started yet) and ask it to provide a server
                        serverSocket = await SpawnServerFromService(url);
                        break;
                    }
                    default:
                        throw new InvalidOperationException("This type of URL is not supported");
                }
            }
            catch (Exception e)
            {
                serverSocketCapturedException = ExceptionDispatchInfo.Capture(e);
            }


            if (serverSocketCapturedException != null)
            {
                try
                {
                    // Notify client that there was an error
                    await clientSocket.WriteStream.WriteInt16Async((short)RouterMessage.ClientServerStarted);
                    await clientSocket.WriteStream.WriteInt32Async(1); // error code Failure
                    await clientSocket.WriteStream.WriteStringAsync(serverSocketCapturedException.SourceException.Message);
                    await clientSocket.WriteStream.FlushAsync();
                }
                finally
                {
                    serverSocketCapturedException.Throw();
                }
            }

            try
            {
                // Notify client that we've found a server for it
                await clientSocket.WriteStream.WriteInt16Async((short)RouterMessage.ClientServerStarted);
                await clientSocket.WriteStream.WriteInt32Async(0); // error code OK
                await clientSocket.WriteStream.FlushAsync();

                // Let's forward clientSocketContext and serverSocketContext
                await await Task.WhenAny(
                    ForwardSocket(clientSocket, serverSocket),
                    ForwardSocket(serverSocket, clientSocket));
            }
            catch
            {
                serverSocket.Dispose();
                throw;
            }
        }