Example #1
0
        public async Task MainLoopAsync(CancellationToken cancel)
        {
            while (cancel.IsCancellationRequested == false)
            {
                try
                {
                    Reload();

                    if (this.Settings.UseAcme)
                    {
                        IsAcmeCertUpdated = false;

                        // Process newly requested ACME certs
                        try
                        {
                            if (this.InternalCertList.Where(x => x.CertType == CertVaultCertType.Acme).Count() < this.Settings.MaxAcmeCerts)
                            {
                                await ProcessEnqueuedAcmeHostnameAsync(cancel);
                            }
                        }
                        catch (Exception ex)
                        {
                            ex._Debug();
                        }

                        if (IsAcmeCertUpdated)
                        {
                            // ACME certificate is added. Reload
                            Reload();
                            IsAcmeCertUpdated = false;
                        }

                        // Process expiring or expires ACME certs
                        try
                        {
                            await ProcessExpiringOrExpiredAcmeCertsAsync(cancel);
                        }
                        catch (Exception ex)
                        {
                            ex._Debug();
                        }

                        if (IsAcmeCertUpdated)
                        {
                            // ACME certificate is added. Reload
                            Reload();
                            IsAcmeCertUpdated = false;
                        }
                    }
                }
                catch (Exception ex)
                {
                    ex._Debug();
                }

                await TaskUtil.AwaitWithPollAsync(this.Settings.ReloadIntervalMsecs, CoresConfig.CertVaultSettings.UpdateIntervalForAcmeQueueCheck, () => this.AcmeQueueUpdatedFlag, cancel);

                this.AcmeQueueUpdatedFlag = false;
            }
        }
        protected override async Task GetValueAsync(SortedDictionary <string, string> ret, RefInt nextPollingInterval, CancellationToken cancel = default)
        {
            SnmpWorkSettings settings = Host.Settings;

            if (settings.PingTargets._IsSamei("none") || settings.PingTargets._IsSamei("null"))
            {
                return;
            }

            string hopsStr = "Hops";

            if (settings.HopsToTTL)
            {
                hopsStr = "TTL";
            }

            string[] pingTargets = settings.PingTargets._Split(StringSplitOptions.RemoveEmptyEntries, ",");

            numPerform++;

            foreach (string pingTarget in pingTargets)
            {
                cancel.ThrowIfCancellationRequested();

                ParseTargetString(pingTarget, out string hostname, out string alias);

                bool ok = false;

                try
                {
                    IPAddress ipAddress = await LocalNet.GetIpAsync(hostname, cancel : cancel);

                    if (FirstPing.IsFirstCall())
                    {
                        // JIT 対策
                        try
                        {
                            await LocalNet.SendPingAsync(ipAddress, pingCancel : cancel);
                        }
                        catch { }
                    }

                    int numTry = 3;

                    if (numPerform >= 2)
                    {
                        // SpeedTest が動作中の場合は SpeedTest が完了するまで待機する
                        await TaskUtil.AwaitWithPollAsync(Timeout.Infinite, 10, () => !SpeedTestClient.IsInProgress, cancel);

                        // 試行回数を指定する
                        numTry = Math.Min(Math.Max(settings.PingNumTry, 1), 100);
                    }

                    SendPingReply reply = await LocalNet.SendPingAndGetBestResultAsync(ipAddress, pingCancel : cancel, numTry : numTry);

                    if (reply.Ok)
                    {
                        double rtt = reply.RttDouble;

                        rtt = Math.Min(rtt, 2.0);

                        int ttl = reply.Ttl;

                        bool ttl_ok = false;

                        if (ttl == 0)
                        {
                            // Use ping command to get TTL
                            try
                            {
                                var result = await EasyExec.ExecAsync(ipAddress.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6?Consts.LinuxCommands.Ping6 : Consts.LinuxCommands.Ping,
                                                                      $"-W 1 -c 1 {ipAddress.ToString()}",
                                                                      cancel : cancel,
                                                                      throwOnErrorExitCode : false);

                                string[] lines = result.OutputStr._GetLines(true);

                                foreach (string line in lines)
                                {
                                    OneLineParams param  = new OneLineParams(line, ' ', false);
                                    string        ttlStr = param._GetStrFirst("ttl");
                                    if (ttlStr._IsFilled())
                                    {
                                        ttl    = ttlStr._ToInt();
                                        ttl_ok = true;
                                        break;
                                    }
                                }
                            }
                            catch (Exception ex)
                            {
                                ex._Debug();
                            }
                        }
                        else
                        {
                            ttl_ok = true;
                        }

                        ret.TryAdd($"Time - {alias}", (rtt * 1000.0).ToString("F3"));


                        if (ttl > 128)
                        {
                            ttl -= 128;
                        }
                        else if (ttl > 64)
                        {
                            ttl -= 64;
                        }

                        int hops = 64 - ttl;

                        if (ttl_ok == false)
                        {
                            hops = 0;
                        }

                        hops._SetMax(0);
                        hops._SetMin(64);

                        ret.TryAdd($"{hopsStr} - {alias}", hops.ToString());

                        ok = true;
                    }
                }
                catch (Exception ex)
                {
                    ex._Debug();
                }

                if (ok == false)
                {
                    ret.TryAdd($"Time - {alias}", "");
                    ret.TryAdd($"{hopsStr} - {alias}", "0");
                }
            }
        }
        async Task ReadMainLoop(CancellationToken cancel)
        {
            try
            {
                var st        = this.Reader.StreamReader;
                int numFailed = 0;

                while (true)
                {
                    await TaskUtil.AwaitWithPollAsync(Timeout.Infinite, this.Emitter !.Options.Delay, () => this.Reader.StreamReader.IsReadyToRead(), cancel);

                    IReadOnlyList <ReadOnlyMemory <byte> > dataToWrite = DequeueAll(out long totalSize, this.Emitter.Options.DefragmentWriteBlockSize);
                    if (totalSize == 0)
                    {
                        if (cancel.IsCancellationRequested)
                        {
                            break;
                        }
                        else
                        {
                            continue;
                        }
                    }

L_RETRY:

                    try
                    {
                        await Emitter.EmitAsync(dataToWrite);

                        numFailed = 0;

                        if (this.Reader.StreamReader.IsReadyToRead() == false)
                        {
                            await Emitter.FlushAsync();
                        }
                    }
                    catch (Exception ex)
                    {
                        ex._Debug();
                        numFailed++;

                        if (cancel.IsCancellationRequested == false)
                        {
                            await cancel._WaitUntilCanceledAsync(Util.GenRandIntervalWithRetry(CoresConfig.LazyWriteBufferSettings.ErrorRetryIntervalStd, numFailed, CoresConfig.LazyWriteBufferSettings.ErrorRetryIntervalMax));

                            goto L_RETRY;
                        }
                        else
                        {
                            break;
                        }
                    }
                }
            }
            finally
            {
                try
                {
                    await Emitter !.CloseAsync();
                }
                catch { }
            }
        }
        protected override async Task GetValueAsync(SortedDictionary <string, string> ret, RefInt nextPollingInterval, CancellationToken cancel = default)
        {
            SnmpWorkSettings settings = Host.Settings;

            if (settings.PingTargets._IsSamei("none") || settings.PingTargets._IsSamei("null"))
            {
                return;
            }

            string[] pingTargets = settings.PingTargets._Split(StringSplitOptions.RemoveEmptyEntries, ",");

            KeyValueList <string, IPAddress> kvList = new KeyValueList <string, IPAddress>();

            // 名前解決
            foreach (string pingTarget in pingTargets)
            {
                cancel.ThrowIfCancellationRequested();

                try
                {
                    ParseTargetString(pingTarget, out string hostname, out string alias);

                    IPAddress ip = await LocalNet.GetIpAsync(hostname, cancel : cancel);

                    kvList.Add(alias, ip);
                }
                catch (Exception ex)
                {
                    ex._Debug();
                }
            }

            List <Task <double> > taskList = new List <Task <double> >();

            int interval = 0;
            int count    = 3;

            // SpeedTest が動作中の場合は SpeedTest が完了するまで待機する
            numPerform++;
            if (numPerform >= 2)
            {
                interval = settings.PktLossIntervalMsec;
                count    = settings.PktLossTryCount;

                await TaskUtil.AwaitWithPollAsync(Timeout.Infinite, 10, () => !SpeedTestClient.IsInProgress, cancel);
            }

            // 並列実行の開始
            foreach (var kv in kvList)
            {
                taskList.Add(PerformOneAsync(kv.Value, count, settings.PktLossTimeoutMsecs, interval, cancel));
            }

            // すべて終了するまで待機し、結果を整理
            for (int i = 0; i < kvList.Count; i++)
            {
                var kv   = kvList[i];
                var task = taskList[i];

                double lossRate = await task._TryAwait();

                double quality = 1.0 - lossRate;

                quality = Math.Max(quality, 0.0);
                quality = Math.Min(quality, 1.0);

                ret.TryAdd($"{kv.Key}", ((double)quality * 100.0).ToString("F3"));
            }
        }