Ejemplo n.º 1
0
        public void DefaultSpawnRequestHandler(SpawnRequestPacket packet, IIncommingMessage message)
        {
            _logger.Debug("Default spawn handler started handling a request to spawn process");

            var controller = _spawners.GetController(packet.SpawnerId);

            if (controller == null)
            {
                message.Respond("Failed to spawn a process. Spawner controller not found", ResponseStatus.Failed);
                return;
            }

            var port = _spawners.GetAvailablePort();

            // Check if we're overriding an IP to master server
            var masterIp = string.IsNullOrEmpty(controller.DefaultSpawnerSettings.MasterIp) ?
                           controller.Connection.ConnectionIp : controller.DefaultSpawnerSettings.MasterIp;

            // Check if we're overriding a port to master server
            var masterPort = controller.DefaultSpawnerSettings.MasterPort < 0 ?
                             controller.Connection.ConnectionPort : controller.DefaultSpawnerSettings.MasterPort;

            // Machine Ip
            var machineIp = controller.DefaultSpawnerSettings.MachineIp;

            // Path to executable
            var path = controller.DefaultSpawnerSettings.ExecutablePath;

            if (string.IsNullOrEmpty(path))
            {
                path = File.Exists(Environment.GetCommandLineArgs()[0])
                    ? Environment.GetCommandLineArgs()[0]
                    : Process.GetCurrentProcess().MainModule.FileName;
            }

            // In case a path is provided with the request
            if (packet.Properties.ContainsKey(OptionKeys.ExecutablePath))
            {
                path = packet.Properties[OptionKeys.ExecutablePath];
            }

            // Get the scene name
            var sceneNameArgument = packet.Properties.ContainsKey(OptionKeys.SceneName)
                ? string.Format("{0} {1} ", CommandLineArgs.Names.LoadScene, packet.Properties[OptionKeys.SceneName])
                : "";

            if (!string.IsNullOrEmpty(packet.OverrideExePath))
            {
                path = packet.OverrideExePath;
            }

            // If spawn in batchmode was set and `DontSpawnInBatchmode` arg is not provided
            var spawnInBatchmode = controller.DefaultSpawnerSettings.SpawnInBatchmode &&
                                   !CommandLineArgs.DontSpawnInBatchmode;

            var startProcessInfo = new ProcessStartInfo(path)
            {
                CreateNoWindow  = false,
                UseShellExecute = false,
                Arguments       = " " +
                                  (spawnInBatchmode ? "-batchmode -nographics " : "") +
                                  (controller.DefaultSpawnerSettings.AddWebGlFlag ? CommandLineArgs.Names.WebGl + " " : "") +
                                  sceneNameArgument +
                                  string.Format("{0} {1} ", CommandLineArgs.Names.MasterIp, masterIp) +
                                  string.Format("{0} {1} ", CommandLineArgs.Names.MasterPort, masterPort) +
                                  string.Format("{0} {1} ", CommandLineArgs.Names.SpawnId, packet.SpawnId) +
                                  string.Format("{0} {1} ", CommandLineArgs.Names.AssignedPort, port) +
                                  string.Format("{0} {1} ", CommandLineArgs.Names.MachineIp, machineIp) +
                                  (CommandLineArgs.DestroyUi ? CommandLineArgs.Names.DestroyUi + " " : "") +
                                  string.Format("{0} \"{1}\" ", CommandLineArgs.Names.SpawnCode, packet.SpawnCode) +
                                  packet.CustomArgs
            };

            _logger.Debug("Starting process with args: " + startProcessInfo.Arguments);

            var processStarted = false;

            try
            {
                new Thread(() =>
                {
                    try
                    {
                        _logger.Debug("New thread started");

                        using (var process = Process.Start(startProcessInfo))
                        {
                            _logger.Debug("Process started. Spawn Id: " + packet.SpawnId + ", pid: " + process.Id);
                            processStarted = true;

                            lock (_processLock)
                            {
                                // Save the process
                                _processes[packet.SpawnId] = process;
                            }

                            var processId = process.Id;

                            // Notify server that we've successfully handled the request
                            AppTimer.ExecuteOnMainThread(() =>
                            {
                                message.Respond(ResponseStatus.Success);
                                controller.NotifyProcessStarted(packet.SpawnId, processId, startProcessInfo.Arguments);
                            });

                            process.WaitForExit();
                        }
                    }
                    catch (Exception e)
                    {
                        if (!processStarted)
                        {
                            AppTimer.ExecuteOnMainThread(() => { message.Respond(ResponseStatus.Failed); });
                        }

                        _logger.Error("An exception was thrown while starting a process. Make sure that you have set a correct build path. " +
                                      "We've tried to start a process at: '" + path + "'. You can change it at 'SpawnerBehaviour' component");
                        _logger.Error(e);
                    }
                    finally
                    {
                        lock (_processLock)
                        {
                            // Remove the process
                            _processes.Remove(packet.SpawnId);
                        }

                        AppTimer.ExecuteOnMainThread(() =>
                        {
                            // Release the port number
                            _spawners.ReleasePort(port);

                            _logger.Debug("Notifying about killed process with spawn id: " + packet.SpawnerId);
                            controller.NotifyProcessKilled(packet.SpawnId);
                        });
                    }
                }).Start();
            }
            catch (Exception e)
            {
                message.Respond(e.Message, ResponseStatus.Error);
                Logs.Error(e);
            }
        }