コード例 #1
0
ファイル: VTFGenerator.cs プロジェクト: marioman0/SprayMaker
 public VTFGenerator(Stream inputStream, Stream outputStream)
 {
     processDelegate = new ProcessAsync(this.Process);
     _output         = new VTFOutput(outputStream);
     _smallInputFile = new MemoryStream();
     inputStream.CopyTo(_smallInputFile);
 }
コード例 #2
0
 public VTFGenerator(Stream inputStream, Stream outputStream)
 {
     processDelegate = new ProcessAsync(this.Process);
     _output = new VTFOutput(outputStream);
     _smallInputFile = new MemoryStream();
     inputStream.CopyTo(_smallInputFile);
 }
コード例 #3
0
        /// <summary>Ensure <paramref name="process"/> is actually running.</summary>
        private async Task <bool> EnsureRunningAsync(ProcessAsync process, CancellationToken token)
        {
            int i = 0;

            while (true)
            {
                i++;

                bool isRunning = await TcpConnectionFactory.IsTorRunningAsync().ConfigureAwait(false);

                if (isRunning)
                {
                    return(true);
                }

                if (process.HasExited)
                {
                    Logger.LogError("Tor process failed to start!");
                    return(false);
                }

                const int MaxAttempts = 25;

                if (i >= MaxAttempts)
                {
                    Logger.LogError($"All {MaxAttempts} attempts to connect to Tor failed.");
                    return(false);
                }

                // Wait 250 milliseconds between attempts.
                await Task.Delay(250, token).ConfigureAwait(false);
            }
        }
コード例 #4
0
        /// <summary>
        /// Stops bitcoin daemon process when PID file exists.
        /// </summary>
        /// <remarks>If there is not PID file, no process is stopped.</remarks>
        /// <param name="onlyOwned">Only stop if this node owns the process.</param>
        public async Task StopAsync(bool onlyOwned)
        {
            Logger.LogDebug($"> {nameof(onlyOwned)}={onlyOwned}");

            if (Process is null)
            {
                Logger.LogDebug("< Process is null.");
                return;
            }

            // "process" variable is guaranteed to be non-null at this point.
            ProcessAsync process = Process;

            using var cts = new CancellationTokenSource(_reasonableCoreShutdownTimeout);
            int?pid = await PidFile.TryReadAsync().ConfigureAwait(false);

            // If the cached PID is PID, then we own the process.
            if (pid.HasValue && (!onlyOwned || CachedPid == pid))
            {
                Logger.LogDebug($"User is responsible for the daemon process with PID {pid}. Stop it.");

                try
                {
                    bool isKilled = false;

                    try
                    {
                        // Stop Bitcoin daemon using RPC "stop" command.
                        // The command actually only initiates the bitcoind graceful shutdown procedure.
                        // Our time budget for the bitcoind to stop is given by "ReasonableCoreShutdownTimeout".
                        await RpcClient.StopAsync().ConfigureAwait(false);
                    }
                    catch (Exception ex)
                    {
                        Logger.LogWarning(ex);
                        process.Kill();
                        isKilled = true;
                    }

                    if (!isKilled)
                    {
                        Logger.LogDebug($"Wait until the process is stopped.");
                        await process.WaitForExitAsync(cts.Token).ConfigureAwait(false);
                    }
                }
                finally
                {
                    Logger.LogDebug($"Wait until the process is stopped.");
                    process.Dispose();
                    Process = null;
                    PidFile.TryDelete();
                }
            }
            else
            {
                Logger.LogDebug("User is NOT responsible for the daemon process.");
            }

            Logger.LogDebug("<");
        }
コード例 #5
0
ファイル: VTFGenerator.cs プロジェクト: marioman0/SprayMaker
        public VTFGenerator(string inputFile, string outputFile)
        {
            processDelegate = new ProcessAsync(this.Process);
            // Create the output directories
            (new FileInfo(outputFile)).Directory.Create();
            _output = new VTFOutput(outputFile);

            _smallInputFile = new FileStream(inputFile, FileMode.Open);
        }
コード例 #6
0
        public VTFGenerator(string inputFile, string outputFile)
        {
            processDelegate = new ProcessAsync(this.Process);
            // Create the output directories
            (new FileInfo(outputFile)).Directory.Create();
            _output = new VTFOutput(outputFile);

            _smallInputFile = new FileStream(inputFile, FileMode.Open);
        }
コード例 #7
0
        /// <remarks>Use the constructor only in tests.</remarks>
        internal LinuxInhibitorTask(InhibitWhat what, TimeSpan period, string reason, ProcessAsync process)
        {
            What       = what;
            BasePeriod = period;
            Reason     = reason;
            Process    = process;
            Cts        = new CancellationTokenSource(period);

            _ = WaitAsync();
        }
コード例 #8
0
 /// <summary>
 /// Subscribes to <see cref="PipeReader"/> and executes <see cref="ProcessAsync"/> whenever
 /// a message was fully received
 /// </summary>
 /// <param name="reader">The reader that provides the data</param>
 /// <param name="processAsync">
 /// The event handler that is invoked every time a message is fully parsed
 /// </param>
 /// <param name="cancellationToken">
 /// The cancellation token that cancels
 /// </param>
 /// <returns>
 /// A task that is completed when <paramref name="cancellationToken"/> is cancelled
 /// </returns>
 public static Task Start(
     PipeReader reader,
     ProcessAsync processAsync,
     CancellationToken cancellationToken)
 {
     return(Task.Factory.StartNew(
                () => ProcessMessagesAsync(reader, processAsync, cancellationToken),
                cancellationToken,
                TaskCreationOptions.LongRunning,
                TaskScheduler.Default));
 }
コード例 #9
0
        public async Task Start_NeverCalled_NotStarted()
        {
            // arrange
            ProcessAsync         a = (_, _) => default;
            Mock <ISocketClient> socketClientMock = new(MockBehavior.Strict);
            ISocketClient        socketClient     = socketClientMock.Object;

            // act
            await using var messagePipeline = new MessagePipeline(socketClient, a);

            // assert
            socketClientMock.VerifyAll();
        }
コード例 #10
0
        public async Task Start_StartOnce_StartDataReceive()
        {
            // arrange
            ProcessAsync     a            = (_, _) => default;
            SocketClientStub socketClient = new() { IsClosed = false };

            await using var messagePipeline = new MessagePipeline(socketClient, a);

            // act
            messagePipeline.Start();
            await socketClient.WaitTillFinished();

            // assert
            Assert.Equal(1, socketClient.GetCallCount(x => x.ReceiveAsync(default !, default !)));
コード例 #11
0
        /// <summary>
        /// Stops bitcoin daemon process when PID file exists.
        /// </summary>
        /// <remarks>If there is not PID file, no process is stopped.</remarks>
        /// <param name="onlyOwned">Only stop if this node owns the process.</param>
        public async Task StopAsync(bool onlyOwned)
        {
            Logger.LogDebug($"> {nameof(onlyOwned)}={onlyOwned}");

            if (Process is null)
            {
                Logger.LogDebug("< Process is null.");
                return;
            }

            ProcessAsync process = Process;             // process is guaranteed to be non-null at this point.

            using var cts = new CancellationTokenSource(ReasonableCoreShutdownTimeout);
            int?pid = await PidFile.TryReadAsync().ConfigureAwait(false);

            // If the cached PID is PID, then we own the process.
            if (pid.HasValue && (!onlyOwned || CachedPid == pid))
            {
                Logger.LogDebug($"User is responsible for the daemon process with PID {pid}. Stop it.");

                try
                {
                    try
                    {
                        await RpcClient.StopAsync().ConfigureAwait(false);
                    }
                    catch (Exception ex)
                    {
                        Logger.LogWarning(ex);
                        process.Kill();
                    }

                    Logger.LogDebug($"Wait until the process is stopped.");
                    await process.WaitForExitAsync(cts.Token).ConfigureAwait(false);
                }
                finally
                {
                    Logger.LogDebug($"Wait until the process is stopped.");
                    process.Dispose();
                    Process = null;
                    PidFile.TryDelete();
                }
            }
            else
            {
                Logger.LogDebug("User is NOT responsible for the daemon process.");
            }

            Logger.LogDebug("<");
        }
コード例 #12
0
        public async Task Constructor_AllArgs_Construct()
        {
            // arrange
            ProcessAsync  a            = (_, _) => default;
            ISocketClient socketClient = new SocketClientStub()
            {
                IsClosed = false
            };

            // act
            await using var messagePipeline = new MessagePipeline(socketClient, a);

            // assert
            Assert.IsType <MessagePipeline>(messagePipeline);
        }
コード例 #13
0
        private static async Task ProcessMessagesAsync(
            PipeReader reader,
            ProcessAsync processAsync,
            CancellationToken cancellationToken)
        {
            try
            {
                while (true)
                {
                    ReadResult result = await reader
                                        .ReadAsync(cancellationToken)
                                        .ConfigureAwait(false);

                    ReadOnlySequence <byte> buffer   = result.Buffer;
                    SequencePosition?       position = null;

                    do
                    {
                        position = buffer.PositionOf(Delimiter);

                        if (position != null)
                        {
                            await processAsync(
                                buffer.Slice(0, position.Value),
                                cancellationToken)
                            .ConfigureAwait(false);

                            // Skip the message which was read.
                            buffer = buffer.Slice(buffer.GetPosition(1, position.Value));
                        }
                    } while (position != null);

                    reader.AdvanceTo(buffer.Start, buffer.End);

                    if (result.IsCompleted)
                    {
                        break;
                    }
                }
            }
            catch (TaskCanceledException) { }
            finally
            {
                await reader.CompleteAsync().ConfigureAwait(false);
            }
        }
コード例 #14
0
        public async void SendCommandImmediateCancelAsync()
        {
            await Assert.ThrowsAsync <TaskCanceledException>(async() =>
            {
                using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));

                var startInfo = new ProcessStartInfo()
                {
                    FileName  = MicroserviceHelpers.GetBinaryPath("bitcoind"),
                    Arguments = "-regtest=1"
                };

                using var process = new ProcessAsync(startInfo);
                process.Start();

                await process.WaitForExitAsync(cts.Token, killOnCancel: true);
            });
        }
コード例 #15
0
        public void Start(
            IPEndPoint endPoint,
            ProcessAsync processRequestAsync)
        {
            if (!this._stop)
            {
                throw new InvalidOperationException($"{nameof(TcpServer)} already started.");
            }

            this.ProcessRequestAsyncCallback = processRequestAsync ?? throw new ArgumentNullException(nameof(processRequestAsync));

            this._stop = false;

            this._cts = new CancellationTokenSource();

            this._listener.Start(endPoint);

            var serverThread = new Thread(Run);

            serverThread.Start();
        }
コード例 #16
0
        /// <summary>
        /// This method can be called only once.
        /// </summary>
        public async Task StartAsync(CancellationToken cancel)
        {
            int    ptcv            = PrintToConsole ? 1 : 0;
            string processPath     = MicroserviceHelpers.GetBinaryPath("bitcoind");
            string networkArgument = NetworkTranslator.GetCommandLineArguments(Network);

            string args = $"{networkArgument} -datadir=\"{DataDir}\" -printtoconsole={ptcv}";

            // Start bitcoind process.
            Process = new ProcessAsync(ProcessStartInfoFactory.Make(processPath, args));
            Process.Start();

            // Store PID in PID file.
            await PidFile.WriteFileAsync(Process.Id).ConfigureAwait(false);

            CachedPid = Process.Id;

            try
            {
                var exceptionTracker = new LastExceptionTracker();

                // Try to connect to bitcoin daemon RPC until we succeed.
                while (true)
                {
                    try
                    {
                        TimeSpan timeSpan = await RpcClient.UptimeAsync(cancel).ConfigureAwait(false);

                        Logger.LogInfo("RPC connection is successfully established.");
                        Logger.LogDebug($"RPC uptime is: {timeSpan}.");

                        // Bitcoin daemon is started. We are done.
                        break;
                    }
                    catch (Exception ex)
                    {
                        ExceptionInfo exceptionInfo = exceptionTracker.Process(ex);

                        // Don't log extensively.
                        if (exceptionInfo.IsFirst)
                        {
                            Logger.LogInfo($"{Constants.BuiltinBitcoinNodeName} is not yet ready... Reason: {exceptionInfo.Exception.Message}");
                        }

                        if (Process is { } p&& p.HasExited)
                        {
                            throw new BitcoindException($"Failed to start daemon, location: '{p.StartInfo.FileName} {p.StartInfo.Arguments}'", ex);
                        }
                    }

                    if (cancel.IsCancellationRequested)
                    {
                        Logger.LogDebug("Bitcoin daemon was not started yet and user requested to cancel the operation.");
                        await StopAsync(onlyOwned : true).ConfigureAwait(false);

                        cancel.ThrowIfCancellationRequested();
                    }

                    // Wait a moment before the next check.
                    await Task.Delay(100, cancel).ConfigureAwait(false);
                }
            }
            catch (Exception)
            {
                Process?.Dispose();
                throw;
            }
        }
コード例 #17
0
        /// <summary>
        /// Installs Tor if it is not installed, then it starts Tor.
        /// </summary>
        /// <param name="ensureRunning">
        /// If <c>false</c>, Tor is started but no attempt to verify that it actually runs is made.
        /// <para>If <c>true</c>, we start Tor and attempt to connect to it to verify it is running (at most 25 attempts).</para>
        /// </param>
        public async Task <bool> StartAsync(bool ensureRunning)
        {
            try
            {
                // Is Tor already running? Either our Tor process from previous Wasabi Wallet run or possibly user's own Tor.
                bool isAlreadyRunning = await TorSocks5Client.IsTorRunningAsync().ConfigureAwait(false);

                if (isAlreadyRunning)
                {
                    string msg = TorSocks5EndPoint is IPEndPoint endpoint
                                                ? $"Tor is already running on {endpoint.Address}:{endpoint.Port}."
                                                : "Tor is already running.";
                    Logger.LogInfo(msg);
                    return(true);
                }

                // Install Tor if it is not installed and verify Tor is not tampered with (using hash/checksum).
                bool verified = await new TorInstallator(Settings).VerifyInstallationAsync().ConfigureAwait(false);

                if (!verified)
                {
                    Logger.LogInfo("Failed to verify Tor installation.");
                    return(false);
                }

                string torArguments = Settings.GetCmdArguments(TorSocks5EndPoint) + $" --Log \"notice file {Settings.LogFilePath}\"";

                var startInfo = new ProcessStartInfo
                {
                    FileName               = Settings.TorBinaryFilePath,
                    Arguments              = torArguments,
                    UseShellExecute        = false,
                    CreateNoWindow         = true,
                    RedirectStandardOutput = true,
                    WorkingDirectory       = Settings.TorDir
                };

                if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                {
                    var env = startInfo.EnvironmentVariables;

                    env["LD_LIBRARY_PATH"] = !env.ContainsKey("LD_LIBRARY_PATH") || string.IsNullOrEmpty(env["LD_LIBRARY_PATH"])
                                                ? Settings.TorBinaryDir
                                                : Settings.TorBinaryDir + Path.PathSeparator + env["LD_LIBRARY_PATH"];

                    Logger.LogDebug($"Environment variable 'LD_LIBRARY_PATH' set to: '{env["LD_LIBRARY_PATH"]}'.");
                }

                TorProcess = new ProcessAsync(startInfo);

                Logger.LogInfo($"Starting Tor process ...");
                TorProcess.Start();

                if (ensureRunning)
                {
                    int i = 0;
                    while (true)
                    {
                        i++;

                        bool isRunning = await TorSocks5Client.IsTorRunningAsync().ConfigureAwait(false);

                        if (isRunning)
                        {
                            break;
                        }

                        const int MaxAttempts = 25;

                        if (i >= MaxAttempts)
                        {
                            Logger.LogError($"All {MaxAttempts} attempts to connect to Tor failed.");
                            return(false);
                        }

                        // Wait 250 milliseconds between attempts.
                        await Task.Delay(250).ConfigureAwait(false);
                    }

                    Logger.LogInfo("Tor is running.");
                    return(true);
                }
            }
            catch (Exception ex)
            {
                Logger.LogError("Could not automatically start Tor. Try running Tor manually.", ex);
            }

            return(false);
        }
コード例 #18
0
    private async Task <(string response, int exitCode)> SendCommandAsync(ProcessStartInfo startInfo, CancellationToken token, Action <StreamWriter>?standardInputWriter = null)
    {
        using var processAsync = new ProcessAsync(startInfo);

        if (standardInputWriter is { })