protected override async Task MainLoopImplAsync(CancellationToken cancel)
        {
            cancel.ThrowIfCancellationRequested();

            GoogleApi.GmailProfile profile;

            try
            {
                profile = await Api !.GmailGetProfileAsync(cancel);

                ClearLastError();
            }
            catch (Exception ex)
            {
                SetLastError(ex);
                throw;
            }

            currentProfile = profile;

            currentAccountInfoStr = profile.emailAddress;

            while (true)
            {
                cancel.ThrowIfCancellationRequested();

                try
                {
                    InboxMessageBox box = await ReloadInternalAsync(cancel);

                    this.InitialLoading = false;

                    ClearLastError();

                    MessageBoxUpdatedCallback(box);
                }
                catch (Exception ex)
                {
                    SetLastError(ex);
                    throw;
                }

                await TaskUtil.WaitObjectsAsync(
                    cancels : cancel._SingleArray(),
                    timeout : Util.GenRandInterval(CoresConfig.InboxGmailAdapterSettings.ReloadInterval));
            }
        }
Beispiel #2
0
        public async Task <bool> FlushAsync(bool halfFlush = false, CancellationToken cancel = default)
        {
            this.Event.Set();

            while (this.GrandCancel.IsCancellationRequested == false && cancel.IsCancellationRequested == false)
            {
                int num;
                lock (this.RecordQueue)
                    num = this.RecordQueue.Count;

                if (halfFlush == false)
                {
                    if (num == 0)
                    {
                        return(true);
                    }
                }
                else
                {
                    if (num <= (this.MaxPendingRecords / 2))
                    {
                        return(true);
                    }
                }

                if (this.GrandCancel.IsCancellationRequested)
                {
                    return(false);
                }
                if (cancel.IsCancellationRequested)
                {
                    return(false);
                }

                var ret = await TaskUtil.WaitObjectsAsync(timeout : 100, cancels : new CancellationToken[] { cancel, this.GrandCancel });

                if (ret == ExceptionWhen.CancelException)
                {
                    return(false);
                }
            }
            return(false);
        }
        public async Task <ConnSock> ConnectAsync(CancellationToken cancel = default)
        {
            if (Flag.IsFirstCall() == false)
            {
                throw new ApplicationException("ConnectAsync() has been already called.");
            }

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

            foreach (var attempt in AttemptList)
            {
                taskList.Add(attempt.ConnectAsyncInternal(this, cancel));
            }

            if (taskList.Count == 0)
            {
                throw new ApplicationException("SpeculativeConnectorBase: The attempt list is empty.");
            }

            while (true)
            {
                var okTask = taskList.Where(x => x.IsCompletedSuccessfully).FirstOrDefault();
                if (okTask != null)
                {
                    // OK
                    PostWaitEvent.Set();
                    taskList.ForEach(x => x._TryWait(true));
                    taskList.Where(x => x != okTask).Where(x => x.IsCompletedSuccessfully)._DoForEach(x => x.Result._DisposeSafe());
                    return(okTask._GetResult());
                }

                taskList.Where(x => x.IsCanceled || x.IsFaulted).ToArray()._DoForEach(x => taskList.Remove(x));

                if (taskList.Count == 0)
                {
                    // Error
                    throw this.ExceptionList.GetException() !;
                }

                await TaskUtil.WaitObjectsAsync(taskList.ToArray(), exceptions : ExceptionWhen.None);
            }
        }
Beispiel #4
0
        public async Task <bool> AddAsync(LogRecord r, LogPendingTreatment pendingTreatment = LogPendingTreatment.Discard, CancellationToken pendingWaitCancel = default)
        {
            if (r.Priority == LogPriority.None)
            {
                return(true);
            }

            if (this.GrandCancel.IsCancellationRequested)
            {
                return(false);
            }

            while (MaxPendingRecords >= 1 && this.RecordQueue.Count >= this.MaxPendingRecords)
            {
                if (pendingTreatment == LogPendingTreatment.WriteForcefully)
                {
                    break;
                }
                else if (pendingTreatment == LogPendingTreatment.Wait)
                {
                    await TaskUtil.WaitObjectsAsync(cancels : new CancellationToken[] { pendingWaitCancel, this.GrandCancel }, events : this.WaitPendingEvent._SingleArray());
                }
                else
                {
                    return(false);
                }
            }

            lock (this.RecordQueue)
            {
                this.RecordQueue.Enqueue(r);
            }

            this.Event.Set();

            return(true);
        }
        // ランダムに配列した各テストを 1 秒間隔で順に実行していき、1 つでも成功したら抜ける
        // 1 つでも成功した場合は true、成功するまでにネットワークの状態が変化した場合は false を返す
        async Task <bool> StartEveryTestAsync(CancellationToken cancel, AsyncAutoResetEvent?networkChangedEvent)
        {
            int startNetworkVersion = (networkChangedEvent == null) ? 0 : TcpIp.GetHostInfo(false).InfoVersion;

            CancellationTokenSource cts = new CancellationTokenSource();

            using (TaskUtil.CreateCombinedCancellationToken(out CancellationToken opCancel, cancel, cts.Token))
            {
                // テストをシャッフルする
                var shuffledTests = Options.GetTestItemList()._Shuffle();

                List <Task <bool> > runningTaskList = new List <Task <bool> >();

                RefBool retBool = new RefBool();

                // シャッフルしたテストを実行する
                int num = 0;
                foreach (var test in shuffledTests)
                {
                    Task <bool> t = AsyncAwait(async() =>
                    {
                        //Con.WriteDebug($"{test} - Waiting {num} secs...");

                        if (await opCancel._WaitUntilCanceledAsync(1000 * num))
                        {
                            // キャンセルされた
                            return(false);
                        }

                        int numRetry = 0;

                        while (true)
                        {
                            if (opCancel.IsCancellationRequested)
                            {
                                return(false);
                            }

                            bool ret = await PerformSingleTestAsync(test, opCancel);

                            //Con.WriteDebug($"{test} - {ret}");

                            if (ret)
                            {
                                // 成功
                                retBool.Set(true);

                                // 自分自信のほか、他のタスクもすべてキャンセルする
                                cts._TryCancelNoBlock();
                                return(true);
                            }

                            // 再試行まで待機
                            numRetry++;

                            int retryInterval = Util.GenRandIntervalWithRetry(Options.RetryIntervalMin, numRetry, Options.RetryIntervalMax);

                            if (test is InternetCheckerPingTestItem)
                            {
                                retryInterval = Util.GenRandIntervalWithRetry(Options.RetryIntervalMin, numRetry, Options.RetryIntervalMaxPing);
                            }

                            await TaskUtil.WaitObjectsAsync(cancels: opCancel._SingleArray(), events: networkChangedEvent._SingleArray(),
                                                            timeout: retryInterval);

                            if (opCancel.IsCancellationRequested)
                            {
                                // キャンセルされた
                                return(false);
                            }

                            if (startNetworkVersion != 0)
                            {
                                int currentNetworkVersion = BackgroundState <PalHostNetInfo> .Current.Version;

                                if (startNetworkVersion != currentNetworkVersion)
                                {
                                    // ネットワーク状態が変化した
                                    // 自分自身のほか、他のタスクもすべてキャンセルする
                                    cts._TryCancelNoBlock();
                                    return(false);
                                }
                            }
                        }
                    });

                    runningTaskList.Add(t);

                    num++;
                }

                // 実行中のテストすべてを待機する
                await Task.WhenAll(runningTaskList);

                return(retBool);
            }
        }
        // メインループ
        async Task MainLoopAsync(CancellationToken cancel)
        {
            while (cancel.IsCancellationRequested == false)
            {
                // インターネットが接続されるまで待機する
                if (await WaitForInternetAsync(cancel) == false)
                {
                    // キャンセルされた
                    return;
                }

                // 接続された
                _IsInternetConnected = true;
                FirstConnectedEvent.Set(true);
                EventListener.FireSoftly(this, NonsenseEventType.Nonsense, true);

                int lastNetworkVersion = TcpIp.GetHostInfo(false).InfoVersion;

                AsyncAutoResetEvent networkChangedEvent = new AsyncAutoResetEvent();
                int eventRegisterId = TcpIp.RegisterHostInfoChangedEvent(networkChangedEvent);
                try
                {
                    // 定期的に、現在もインターネットに接続されているかどうか確認する
                    while (cancel.IsCancellationRequested == false)
                    {
                        // 一定時間待つ ただしネットワーク状態の変化が発生したときは待ちを解除する
                        await TaskUtil.WaitObjectsAsync(cancels : cancel._SingleArray(), events : networkChangedEvent._SingleArray(),
                                                        timeout : Options.CheckIntervalAfterEstablished);

                        if (cancel.IsCancellationRequested)
                        {
                            break;
                        }

                        // 接続検査を再実行する
                        // ただし、今度はタイムアウトを設定する
                        CancellationTokenSource timeoutCts = new CancellationTokenSource();
                        timeoutCts.CancelAfter(Options.TimeoutToDetectDisconnected);

                        bool ret = await StartEveryTestAsync(timeoutCts.Token, null);

                        if (cancel.IsCancellationRequested)
                        {
                            break;
                        }

                        if (ret == false)
                        {
                            // 接続試験に失敗 (タイムアウト発生)
                            // 切断された
                            _IsInternetConnected = false;
                            FirstDisconnectedEvent.Set(true);
                            EventListener.FireSoftly(this, NonsenseEventType.Nonsense, false);

                            break;
                        }
                    }
                }
                finally
                {
                    TcpIp.UnregisterHostInfoChangedEvent(eventRegisterId);
                }
            }
        }
Beispiel #7
0
        async Task ServerMainLoop(CancellationToken mainLoopCancel)
        {
            if (Once.IsFirstCall() == false)
            {
                throw new ApplicationException("You cannot reuse the object.");
            }

            using (var sessions = new GroupManager <ulong, SessionData>(
                       onNewGroup: (key, state) =>
            {
                Dbg.Where($"New session: {key}");
                return(new SessionData());
            },
                       onDeleteGroup: (key, ctx, state) =>
            {
                Dbg.Where($"Delete session: {key}");
            }))
            {
                var listener = System.CreateListener(new TcpListenParam(async(lx, sock) =>
                {
                    Con.WriteLine($"Connected {sock.Info.Tcp.RemoteIPAddress}:{sock.Info.Tcp.RemotePort} -> {sock.Info.Tcp.LocalIPAddress}:{sock.Info.Tcp.LocalPort}");

                    var app = sock.GetNetAppProtocolStub();

                    var st = app.GetStream();

                    var attachHandle = app.AttachHandle;

                    attachHandle.SetStreamReceiveTimeout(RecvTimeout);

                    await st.SendAsync("TrafficServer\r\n\0"._GetBytes_Ascii());

                    ReadOnlyMemoryBuffer <byte> buf = await st.ReceiveAsync(17);

                    Direction dir   = buf.ReadBool8() ? Direction.Send : Direction.Recv;
                    ulong sessionId = 0;
                    long timespan   = 0;

                    try
                    {
                        sessionId = buf.ReadUInt64();
                        timespan  = buf.ReadSInt64();
                    }
                    catch { }

                    long recvEndTick = FastTick64.Now + timespan;
                    if (timespan == 0)
                    {
                        recvEndTick = long.MaxValue;
                    }

                    using (var session = sessions.Enter(sessionId))
                    {
                        using (var delay = new DelayAction((int)(Math.Min(timespan * 3 + 180 * 1000, int.MaxValue)), x => app._CancelSafe(new TimeoutException())))
                        {
                            if (dir == Direction.Recv)
                            {
                                RefInt refTmp  = new RefInt();
                                long totalSize = 0;

                                while (true)
                                {
                                    var ret = await st.FastReceiveAsync(totalRecvSize: refTmp);
                                    if (ret.Count == 0)
                                    {
                                        break;
                                    }
                                    totalSize += refTmp;

                                    if (ret[0].Span[0] == (byte)'!')
                                    {
                                        break;
                                    }

                                    if (FastTick64.Now >= recvEndTick)
                                    {
                                        break;
                                    }
                                }

                                attachHandle.SetStreamReceiveTimeout(Timeout.Infinite);
                                attachHandle.SetStreamSendTimeout(60 * 5 * 1000);

                                session.Context.NoMoreData = true;

                                while (true)
                                {
                                    MemoryBuffer <byte> sendBuf = new MemoryBuffer <byte>();
                                    sendBuf.WriteSInt64(totalSize);

                                    await st.SendAsync(sendBuf);

                                    await Task.Delay(100);
                                }
                            }
                            else
                            {
                                attachHandle.SetStreamReceiveTimeout(Timeout.Infinite);
                                attachHandle.SetStreamSendTimeout(Timeout.Infinite);

                                while (true)
                                {
                                    if (sessionId == 0 || session.Context.NoMoreData == false)
                                    {
                                        await st.SendAsync(SendData);
                                    }
                                    else
                                    {
                                        var recvMemory = await st.ReceiveAsync();

                                        if (recvMemory.Length == 0)
                                        {
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                                                                        "SpeedTest",
                                                                        this.ServerPorts));

                try
                {
                    Con.WriteLine("Listening.");

                    await TaskUtil.WaitObjectsAsync(cancels : mainLoopCancel._SingleArray());
                }
                finally
                {
                    await listener._DisposeWithCleanupSafeAsync();
                }
            }
        }
Beispiel #8
0
        async Task <Result> ClientSingleConnectionAsync(Direction dir, AsyncManualResetEvent fireMeWhenReady, CancellationToken cancel)
        {
            Result ret = new Result();

            using (NetPalTcpProtocolStub tcp = new NetPalTcpProtocolStub(cancel: cancel))
            {
                await tcp.ConnectAsync(ServerIP, ServerPort, cancel, ConnectTimeout);

                using (ConnSock sock = new ConnSock(tcp))
                {
                    NetAppStub app = sock.GetNetAppProtocolStub();

                    AttachHandle attachHandle = app.AttachHandle;

                    PipeStream st = app.GetStream();

                    if (dir == Direction.Recv)
                    {
                        app.AttachHandle.SetStreamReceiveTimeout(RecvTimeout);
                    }

                    try
                    {
                        var hello = await st.ReceiveAllAsync(16);

                        if (hello.Span.ToArray()._GetString_Ascii().StartsWith("TrafficServer\r\n") == false)
                        {
                            throw new ApplicationException("Target server is not a Traffic Server.");
                        }

                        //throw new ApplicationException("aaaa" + dir.ToString());

                        fireMeWhenReady.Set();

                        cancel.ThrowIfCancellationRequested();

                        await TaskUtil.WaitObjectsAsync(
                            manualEvents : ClientStartEvent._SingleArray(),
                            cancels : cancel._SingleArray()
                            );

                        long tickStart = FastTick64.Now;
                        long tickEnd   = tickStart + this.TimeSpan;

                        var sendData = new MemoryBuffer <byte>();
                        sendData.WriteBool8(dir == Direction.Recv);
                        sendData.WriteUInt64(SessionId);
                        sendData.WriteSInt64(TimeSpan);

                        await st.SendAsync(sendData);

                        if (dir == Direction.Recv)
                        {
                            RefInt totalRecvSize = new RefInt();
                            while (true)
                            {
                                long now = FastTick64.Now;

                                if (now >= tickEnd)
                                {
                                    break;
                                }

                                await TaskUtil.WaitObjectsAsync(
                                    tasks : st.FastReceiveAsync(totalRecvSize : totalRecvSize)._SingleArray(),
                                    timeout : (int)(tickEnd - now),
                                    exceptions : ExceptionWhen.TaskException | ExceptionWhen.CancelException);

                                ret.NumBytesDownload += totalRecvSize;
                            }
                        }
                        else
                        {
                            attachHandle.SetStreamReceiveTimeout(Timeout.Infinite);

                            while (true)
                            {
                                long now = FastTick64.Now;

                                if (now >= tickEnd)
                                {
                                    break;
                                }

                                /*await WebSocketHelper.WaitObjectsAsync(
                                 *  tasks: st.FastSendAsync(SendData, flush: true).ToSingleArray(),
                                 *  timeout: (int)(tick_end - now),
                                 *  exceptions: ExceptionWhen.TaskException | ExceptionWhen.CancelException);*/

                                await st.FastSendAsync(SendData, flush : true);
                            }

                            Task recvResult = Task.Run(async() =>
                            {
                                var recvMemory = await st.ReceiveAllAsync(8);

                                MemoryBuffer <byte> recvMemoryBuf = recvMemory;
                                ret.NumBytesUpload = recvMemoryBuf.ReadSInt64();

                                st.Disconnect();
                            });

                            Task sendSurprise = Task.Run(async() =>
                            {
                                byte[] surprise = new byte[260];
                                surprise.AsSpan().Fill((byte)'!');
                                while (true)
                                {
                                    await st.SendAsync(surprise);

                                    await TaskUtil.WaitObjectsAsync(
                                        manualEvents: sock.Pipe.OnDisconnectedEvent._SingleArray(),
                                        timeout: 200);
                                }
                            });

                            await WhenAll.Await(false, recvResult, sendSurprise);

                            await recvResult;
                        }

                        st.Disconnect();
                        return(ret);
                    }
                    catch (Exception ex)
                    {
                        ExceptionQueue !.Add(ex);
                        throw;
                    }
                }
            }
        }
Beispiel #9
0
        public async Task <Result?> RunClientAsync()
        {
            CurrentCount.Increment();

            try
            {
                if (Once.IsFirstCall() == false)
                {
                    throw new ApplicationException("You cannot reuse the object.");
                }

                Con.WriteLine("Client mode start");

                ExceptionQueue = new ExceptionQueue();
                SessionId      = Util.RandUInt64();

                List <Task <Result> >        tasks       = new List <Task <Result> >();
                List <AsyncManualResetEvent> readyEvents = new List <AsyncManualResetEvent>();

                using (CancelWatcher cancelWatcher = new CancelWatcher(this.Cancel))
                {
                    for (int i = 0; i < NumConnection; i++)
                    {
                        Direction dir;
                        if (Mode == SpeedTestModeFlag.Download)
                        {
                            dir = Direction.Recv;
                        }
                        else if (Mode == SpeedTestModeFlag.Upload)
                        {
                            dir = Direction.Send;
                        }
                        else
                        {
                            dir = ((i % 2) == 0) ? Direction.Recv : Direction.Send;
                        }

                        AsyncManualResetEvent readyEvent = new AsyncManualResetEvent();
                        var t = ClientSingleConnectionAsync(dir, readyEvent, cancelWatcher.CancelToken);
                        ExceptionQueue.RegisterWatchedTask(t);
                        tasks.Add(t);
                        readyEvents.Add(readyEvent);
                    }

                    try
                    {
                        using (var whenAllReady = new WhenAll(readyEvents.Select(x => x.WaitAsync())))
                        {
                            await TaskUtil.WaitObjectsAsync(
                                tasks : tasks.Append(whenAllReady.WaitMe).ToArray(),
                                cancels : cancelWatcher.CancelToken._SingleArray(),
                                manualEvents : ExceptionQueue.WhenExceptionAdded._SingleArray());
                        }

                        Cancel.ThrowIfCancellationRequested();
                        ExceptionQueue.ThrowFirstExceptionIfExists();

                        ExceptionQueue.WhenExceptionAdded.CallbackList.AddSoftCallback(x =>
                        {
                            cancelWatcher.Cancel();
                        });

                        using (new DelayAction(TimeSpan * 3 + 180 * 1000, x =>
                        {
                            cancelWatcher.Cancel();
                        }, doNotBlockOnDispose: true))
                        {
                            ClientStartEvent.Set(true);

                            using (var whenAllCompleted = new WhenAll(tasks))
                            {
                                await TaskUtil.WaitObjectsAsync(
                                    tasks : whenAllCompleted.WaitMe._SingleArray(),
                                    cancels : cancelWatcher.CancelToken._SingleArray()
                                    );

                                await whenAllCompleted.WaitMe;
                            }
                        }

                        Result ret = new Result();

                        ret.Span = TimeSpan;

                        foreach (var r in tasks.Select(x => x._GetResult()))
                        {
                            ret.NumBytesDownload += r.NumBytesDownload;
                            ret.NumBytesUpload   += r.NumBytesUpload;
                        }

                        ret.NumBytesTotal = ret.NumBytesUpload + ret.NumBytesDownload;

                        ret.BpsUpload   = (long)((double)ret.NumBytesUpload * 1000.0 * 8.0 / (double)ret.Span * 1514.0 / 1460.0);
                        ret.BpsDownload = (long)((double)ret.NumBytesDownload * 1000.0 * 8.0 / (double)ret.Span * 1514.0 / 1460.0);
                        ret.BpsTotal    = ret.BpsUpload + ret.BpsDownload;

                        return(ret);
                    }
                    catch (Exception ex)
                    {
                        await Task.Yield();

                        ExceptionQueue.Add(ex);
                    }
                    finally
                    {
                        cancelWatcher.Cancel();
                        try
                        {
                            await Task.WhenAll(tasks);
                        }
                        catch { }
                    }

                    ExceptionQueue.ThrowFirstExceptionIfExists();
                }

                return(null);
            }
            finally
            {
                CurrentCount.Decrement();
            }
        }
Beispiel #10
0
        protected override async Task MainLoopImplAsync(CancellationToken cancel)
        {
            MessageListPerConversation.Clear();

            cancel.ThrowIfCancellationRequested();

            CancellationTokenSource realTimeTaskCancel = new CancellationTokenSource();

            Task realTimeTask = RealtimeRecvLoopAsync(realTimeTaskCancel.Token);

            try
            {
                bool all = true;
                string[]? targetChannelIdList = null;

                while (true)
                {
                    cancel.ThrowIfCancellationRequested();

                    ExceptionWhen reason;

                    try
                    {
                        InboxMessageBox box = await ReloadInternalAsync(all, targetChannelIdList, cancel);

                        ClearLastError();

                        this.InitialLoading = false;

                        MessageBoxUpdatedCallback(box);

                        if (this.UpdateChannelsList.Count == 0)
                        {
                            reason = await TaskUtil.WaitObjectsAsync(
                                cancels : cancel._SingleArray(),
                                events : this.UpdateChannelsEvent._SingleArray(),
                                timeout : Util.GenRandInterval(CoresConfig.InboxSlackAdapterSettings.RefreshAllInterval));
                        }
                        else
                        {
                            reason = ExceptionWhen.None;
                        }
                    }
                    catch (Exception ex)
                    {
                        SetLastError(ex._GetSingleException());

                        ex._Debug();

                        reason = ExceptionWhen.TimeoutException;

                        await cancel._WaitUntilCanceledAsync(15000);
                    }

                    if (reason == ExceptionWhen.TimeoutException)
                    {
                        all = true;
                        targetChannelIdList = null;
                        lock (this.UpdateChannelsListLock)
                        {
                            this.UpdateChannelsList.Clear();
                        }
                    }
                    else
                    {
                        all = false;
                        lock (this.UpdateChannelsListLock)
                        {
                            targetChannelIdList = this.UpdateChannelsList.ToArray();
                            this.UpdateChannelsList.Clear();
                        }
                    }
                }
            }
            finally
            {
                realTimeTaskCancel._TryCancel();

                await realTimeTask._TryWaitAsync(true);
            }
        }