public TelnetStreamWatcherBase(TelnetStreamWatcherOptions options)
        {
            this.Options = options;

            Listener = TcpIp.CreateListener(new TcpListenParam(async(listener, sock) =>
            {
                try
                {
                    Con.WriteDebug($"TelnetStreamWatcher({this.ToString()}: Connected: {sock.EndPointInfo._GetObjectDump()}");

                    using (var destStream = sock.GetStream())
                    {
                        if (sock.Info.Ip.RemoteIPAddress == null || Options.IPAccessFilter(sock.Info.Ip.RemoteIPAddress) == false)
                        {
                            Con.WriteDebug($"TelnetStreamWatcher({this.ToString()}: Access denied: {sock.EndPointInfo._GetObjectDump()}");

                            await destStream.WriteAsync("You are not allowed to access to this service.\r\n\r\n"._GetBytes_Ascii());

                            await Task.Delay(100);

                            return;
                        }

                        using (var pipePoint = await SubscribeImplAsync())
                        {
                            // ソケットから Enter キー入力を待機する
                            Task keyInputTask = TaskUtil.StartAsyncTaskAsync(async() =>
                            {
                                using StreamReader lineReader = new StreamReader(destStream);

                                while (true)
                                {
                                    string?line = await lineReader.ReadLineAsync();

                                    if (line == null)
                                    {
                                        break;
                                    }

                                    line = line.Trim();

                                    if (line._IsSamei("s"))
                                    {
                                        // Socket リストの表示
                                        var list = LocalNet.GetSockList().OrderBy(x => x.Connected);

                                        StringWriter w = new StringWriter();

                                        w.WriteLine();

                                        foreach (var sock in list)
                                        {
                                            string tmp = sock._GetObjectDump();
                                            w.WriteLine(tmp);
                                        }

                                        w.WriteLine();

                                        w.WriteLine($"Total sockets: {list.Count()}");

                                        w.WriteLine();

                                        byte[] data = w.ToString()._GetBytes_Ascii();

                                        var pipe = pipePoint;
                                        if (pipe.CounterPart != null)
                                        {
                                            lock (pipe.CounterPart.StreamWriter.LockObj)
                                            {
                                                if (pipe.CounterPart.StreamWriter.NonStopWriteWithLock(data, false, FastStreamNonStopWriteMode.DiscardExistingData) != 0)
                                                {
                                                    // To avoid deadlock, CompleteWrite() must be called from other thread.
                                                    // (CompleteWrite() ==> Disconnect ==> Socket Log will recorded ==> ReceiveLog() ==> this function will be called!)
                                                    TaskUtil.StartSyncTaskAsync(() => pipe.CounterPart.StreamWriter.CompleteWrite(false), false, false)._LaissezFaire(true);
                                                }
                                            }
                                        }
                                    }
                                    else
                                    {
                                        // GC
                                        Dbg.WriteLine($"Manual GC is called by the administrator.");

                                        long start = FastTick64.Now;
                                        Dbg.GcCollect();
                                        long end = FastTick64.Now;

                                        long spentTime = end - start;

                                        Dbg.WriteLine($"Manual GC Took Time: {spentTime} msecs.");
                                    }
                                }
                            });

                            try
                            {
                                // ソケットに対して、pipePoint のストリームをそのまま非同期で流し込む
                                using (var pipeStub = pipePoint.GetNetAppProtocolStub())
                                    using (var srcStream = pipeStub.GetStream())
                                    {
                                        await srcStream.CopyToAsync(destStream, sock.GrandCancel);
                                    }
                            }
                            finally
                            {
                                await UnsubscribeImplAsync(pipePoint);

                                await pipePoint.CleanupAsync(new DisconnectedException());

                                await keyInputTask._TryAwait(noDebugMessage: true);
                            }
                        }
                    }
                }
                finally
                {
                    Con.WriteDebug($"TelnetStreamWatcher({this.ToString()}: Disconnected: {sock.EndPointInfo._GetObjectDump()}");
                }
            },
                                                               "TelnetStreamWatcher",
                                                               this.Options.EndPoints.ToArray()));

            this.AddIndirectDisposeLink(this.Listener);
        }
Example #2
0
        public async Task StartWebSocketClientAsync(string uri, CancellationToken cancel = default)
        {
            if (Started.IsFirstCall() == false)
            {
                throw new ApplicationException("Already started.");
            }

            LowerStream.ReadTimeout  = Options.TimeoutOpen;
            LowerStream.WriteTimeout = Options.TimeoutOpen;

            Uri u = new Uri(uri);
            HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Get, uri);

            byte[] nonce      = Secure.Rand(16);
            string requestKey = Convert.ToBase64String(nonce);

            req.Headers.Add("Host", u.Host);
            req.Headers.Add("User-Agent", Options.UserAgent);
            req.Headers.Add("Accept", Consts.MimeTypes.Html);
            req.Headers.Add("Sec-WebSocket-Version", "13");
            req.Headers.Add("Origin", "null");
            req.Headers.Add("Sec-WebSocket-Key", requestKey);
            req.Headers.Add("Connection", "keep-alive, Upgrade");
            req.Headers.Add("Pragma", "no-cache");
            req.Headers.Add("Cache-Control", "no-cache");
            req.Headers.Add("Upgrade", "websocket");

            StringWriter tmpWriter = new StringWriter();

            tmpWriter.WriteLine($"{req.Method} {req.RequestUri.PathAndQuery} HTTP/1.1");
            tmpWriter.WriteLine(req.Headers.ToString());

            await LowerStream.WriteAsync(tmpWriter.ToString()._GetBytes_UTF8(), cancel);

            Dictionary <string, string> headers = new Dictionary <string, string>(StrComparer.IgnoreCaseComparer);
            int num          = 0;
            int responseCode = 0;

            StreamReader tmpReader = new StreamReader(LowerStream);

            while (true)
            {
                string line = await TaskUtil.DoAsyncWithTimeout((procCancel) => tmpReader.ReadLineAsync(),
                                                                timeout : Options.TimeoutOpen,
                                                                cancel : cancel);

                if (line == "")
                {
                    break;
                }

                if (num == 0)
                {
                    string[] tokens = line.Split(' ');
                    if (tokens[0] != "HTTP/1.1")
                    {
                        throw new ApplicationException($"Cannot establish the WebSocket Protocol. Response: \"{tokens}\"");
                    }
                    responseCode = int.Parse(tokens[1]);
                }
                else
                {
                    string[] tokens = line.Split(':');
                    string   name   = tokens[0].Trim();
                    string   value  = tokens[1].Trim();
                    headers[name] = value;
                }

                num++;
            }

            if (responseCode != 101)
            {
                throw new ApplicationException($"Cannot establish the WebSocket Protocol. Perhaps the destination host does not support WebSocket. Wrong response code: \"{responseCode}\"");
            }

            if (headers["Upgrade"].Equals("websocket", StringComparison.InvariantCultureIgnoreCase) == false)
            {
                throw new ApplicationException($"Wrong Upgrade header: \"{headers["Upgrade"]}\"");
            }

            string acceptKey  = headers["Sec-WebSocket-Accept"];
            string keyCalcStr = requestKey + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
            SHA1   sha1       = new SHA1Managed();
            string acceptKey2 = Convert.ToBase64String(sha1.ComputeHash(keyCalcStr._GetBytes_Ascii()));

            if (acceptKey != acceptKey2)
            {
                throw new ApplicationException($"Wrong accept_key: \'{acceptKey}\'");
            }

            this.SendTask = SendLoopAsync();
            this.RecvTask = RecvLoopAsync();
        }
Example #3
0
        async Task RecvLoopAsync()
        {
            try
            {
                CancellationToken cancel = this.GrandCancel;

                LowerStream.ReadTimeout = Options.TimeoutComm;

                MemoryBuffer <byte> currentRecvingMessage = new MemoryBuffer <byte>();

                while (true)
                {
                    byte b1 = await LowerStream.ReceiveByteAsync(cancel).FlushOtherStreamIfPending(UpperStream);

                    WebSocketOpcode opcode = (WebSocketOpcode)(b1 & 0x0f);

                    byte b2 = await LowerStream.ReceiveByteAsync(cancel);

                    bool isMasked = (b2 & 0b10000000)._ToBool();
                    int  tmp      = (b2 & 0b01111111);

                    ulong payloadLen64 = 0;
                    if (tmp <= 125)
                    {
                        payloadLen64 = (ulong)tmp;
                    }
                    else if (tmp == 126)
                    {
                        payloadLen64 = await LowerStream.ReceiveUInt16Async(cancel).FlushOtherStreamIfPending(UpperStream);
                    }
                    else if (tmp == 127)
                    {
                        payloadLen64 = await LowerStream.ReceiveUInt64Async(cancel).FlushOtherStreamIfPending(UpperStream);
                    }

                    if (payloadLen64 > (ulong)Options.RecvMaxPayloadLenPerFrame)
                    {
                        throw new ApplicationException($"payloadLen64 {payloadLen64} > Options.RecvMaxPayloadLenPerFrame {Options.RecvMaxPayloadLenPerFrame}");
                    }

                    int payloadLen = (int)payloadLen64;

                    Memory <byte> maskKey = default;

                    if (isMasked)
                    {
                        maskKey = await LowerStream.ReceiveAllAsync(4, cancel).FlushOtherStreamIfPending(UpperStream);
                    }

                    Memory <byte> data = await LowerStream.ReceiveAllAsync(payloadLen, cancel).FlushOtherStreamIfPending(UpperStream);

                    if (isMasked)
                    {
                        TaskUtil.Sync(() =>
                        {
                            Span <byte> maskKeySpan = maskKey.Span;
                            Span <byte> dataSpan    = data.Span;
                            for (int i = 0; i < dataSpan.Length; i++)
                            {
                                dataSpan[i] = (byte)(dataSpan[i] ^ maskKeySpan[i % 4]);
                            }
                        });
                    }

                    if (opcode.EqualsAny(WebSocketOpcode.Text, WebSocketOpcode.Bin, WebSocketOpcode.Continue))
                    {
                        if (Options.RespectMessageDelimiter == false)
                        {
                            if (data.Length >= 1)
                            {
                                await UpperStream.WaitReadyToSendAsync(cancel, Timeout.Infinite);

                                UpperStream.FastSendNonBlock(data, false);
                            }
                        }
                        else
                        {
                            bool isFin = (b1 & 0b10000000)._ToBool();

                            if (isFin && opcode.EqualsAny(WebSocketOpcode.Text, WebSocketOpcode.Bin))
                            {
                                // Single message
                                if (data.Length >= 1)
                                {
                                    await UpperStream.WaitReadyToSendAsync(cancel, Timeout.Infinite);

                                    UpperStream.FastSendNonBlock(data, false);
                                }
                            }
                            else if (isFin == false && opcode.EqualsAny(WebSocketOpcode.Text, WebSocketOpcode.Bin))
                            {
                                // First message
                                currentRecvingMessage.Clear();

                                if ((currentRecvingMessage.Length + data.Length) >= Options.RecvMaxTotalFragmentSize)
                                {
                                    throw new ApplicationException("WebSocket: Exceeding Options.RecvMaxTotalFragmentSize.");
                                }

                                currentRecvingMessage.Write(data);
                            }
                            else if (isFin && opcode == WebSocketOpcode.Continue)
                            {
                                // Final continuous message
                                if ((currentRecvingMessage.Length + data.Length) >= Options.RecvMaxTotalFragmentSize)
                                {
                                    throw new ApplicationException("WebSocket: Exceeding Options.RecvMaxTotalFragmentSize.");
                                }

                                currentRecvingMessage.Write(data);

                                if (currentRecvingMessage.Length >= 1)
                                {
                                    await UpperStream.WaitReadyToSendAsync(cancel, Timeout.Infinite);

                                    UpperStream.FastSendNonBlock(data, false);
                                }

                                currentRecvingMessage.Clear();
                            }
                            else if (isFin == false && opcode == WebSocketOpcode.Continue)
                            {
                                // Intermediate continuous message
                                if ((currentRecvingMessage.Length + data.Length) >= Options.RecvMaxTotalFragmentSize)
                                {
                                    throw new ApplicationException("WebSocket: Exceeding Options.RecvMaxTotalFragmentSize.");
                                }

                                currentRecvingMessage.Write(data);
                            }
                        }
                    }
                    else if (opcode == WebSocketOpcode.Pong)
                    {
                        lock (this.PongQueueLock)
                        {
                            this.PongQueue.Enqueue(data);
                        }
                        this.SendPongEvent.Set(true);
                    }
                    else if (opcode == WebSocketOpcode.Ping)
                    {
                        lock (this.PongQueueLock)
                        {
                            this.PongQueue.Enqueue(data);
                        }
                        this.SendPongEvent.Set(true);
                    }
                    else if (opcode == WebSocketOpcode.Close)
                    {
                        throw new DisconnectedException();
                    }
                    else
                    {
                        throw new ApplicationException($"WebSocket: Unknown Opcode: {(int)opcode}");
                    }
                }
            }
            catch (Exception ex)
            {
                this.UpperStream.Disconnect();
                this.Cancel(ex);
            }
        }
        // メインループ
        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);
                }
            }
        }
        // ランダムに配列した各テストを 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);
            }
        }
Example #6
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;
                    }
                }
            }
        }
Example #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();
                }
            }
        }
        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 { }
            }
        }
Example #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();
            }
        }
        public void Show()
        {
            HiveData.SyncWithStorage(HiveSyncFlags.LoadFromFile, true);

            long pid  = HiveData.ManagedData.Pid;
            int  port = HiveData.ManagedData.LocalLogWatchPort;

            if (pid != 0 && port != 0)
            {
                Con.WriteLine("Starting the real-time log session.");
                Con.WriteLine("Pressing Ctrl + D or Ctrl + Q to disconnect the session.");
                Con.WriteLine();

                Con.WriteLine($"Connecting to localhost:{port} ...");

                CancellationTokenSource cancelSource = new CancellationTokenSource();
                CancellationToken       cancel       = cancelSource.Token;

                Task task = TaskUtil.StartAsyncTaskAsync(async() =>
                {
                    try
                    {
                        using (var sock = await LocalNet.ConnectAsync(new TcpConnectParam(IPAddress.Loopback, port), cancel))
                            using (var stream = sock.GetStream())
                                using (MemoryHelper.FastAllocMemoryWithUsing(65536, out Memory <byte> tmp))
                                {
                                    Con.WriteLine("The real-time log session is connected.");
                                    Con.WriteLine();
                                    try
                                    {
                                        while (true)
                                        {
                                            int r = await stream.ReadAsync(tmp, cancel);
                                            if (r <= 0)
                                            {
                                                break;
                                            }
                                            ReadOnlyMemory <byte> data = tmp.Slice(0, r);
                                            string s = Str.Utf8Encoding.GetString(data.Span);
                                            Console.Write(s);
                                        }
                                    }
                                    catch { }

                                    Con.WriteLine();
                                    Con.WriteLine("The real-time log session is disconnected.");
                                }
                    }
                    catch (Exception ex)
                    {
                        Con.WriteError(ex.Message);
                    }
                });

                try
                {
                    while (true)
                    {
                        var key = Console.ReadKey();
                        if ((key.Key == ConsoleKey.D || key.Key == ConsoleKey.Q) && key.Modifiers == ConsoleModifiers.Control)
                        {
                            break;
                        }
                    }
                }
                catch { }

                cancelSource._TryCancelNoBlock();

                task._TryWait(true);
            }
            else
            {
                Con.WriteLine($"The daemon \"{Name}\" is not running.");
            }
        }
Example #11
0
        static void StartUpdateLoop()
        {
            UpdateMainLoopTaskCancel = new CancellationTokenSource();

            UpdateMainLoopTask = TaskUtil.StartAsyncTaskAsync(UpdateRepositoryMainLoopAsync);
        }
        public void ExecMain()
        {
            if (Once.IsFirstCall() == false)
            {
                throw new ApplicationException("StartMainLoop can be called only once.");
            }

            this.SingleInstance = new SingleInstance($"UserModeService_{this.Name}");

            try
            {
                string?         eventName   = null;
                EventWaitHandle?eventHandle = null;

                if (Env.IsUnix)
                {
                    System.Runtime.Loader.AssemblyLoadContext.Default.Unloading += UnixSigTermHandler;
                }
                else
                {
                    eventName = @"Global\usermodesvc_" + Util.Rand(16)._GetHexString().ToLower();

                    eventHandle = new EventWaitHandle(false, EventResetMode.ManualReset, eventName);

                    TaskUtil.StartSyncTaskAsync(() =>
                    {
                        eventHandle.WaitOne();

                        Win32PipeRecvHandler();
                    }, leakCheck: false)._LaissezFaire(true);
                }

                // Start the TelnetLogWatcher
                List <IPEndPoint> telnetWatcherEpList = new List <IPEndPoint>();

                telnetWatcherEpList.Add(new IPEndPoint(IPAddress.Loopback, HiveData.ManagedData.LocalLogWatchPort));
                telnetWatcherEpList.Add(new IPEndPoint(IPAddress.IPv6Loopback, HiveData.ManagedData.LocalLogWatchPort));

                if (this.TelnetLogWatcherPort != 0)
                {
                    telnetWatcherEpList.Add(new IPEndPoint(IPAddress.Any, this.TelnetLogWatcherPort));
                    telnetWatcherEpList.Add(new IPEndPoint(IPAddress.IPv6Any, this.TelnetLogWatcherPort));
                }

                TelnetWatcher = new TelnetLocalLogWatcher(new TelnetStreamWatcherOptions((ip) => ip._GetIPAddressType().BitAny(IPAddressType.LocalUnicast | IPAddressType.Loopback), null,
                                                                                         telnetWatcherEpList.ToArray()));

                InternalStart();

                lock (HiveData.DataLock)
                {
                    HiveData.ManagedData.Pid       = Env.ProcessId;
                    HiveData.ManagedData.EventName = eventName;
                }

                HiveData.SyncWithStorage(HiveSyncFlags.SaveToFile, true);

                // Save pid
                string pidFileName = Lfs.PathParser.Combine(CoresConfig.UserModeServiceSettings.GetLocalHiveDirProc.Value(), this.Name + ".pid");
                string pidBody     = Env.ProcessId.ToString() + Env.NewLine;
                Lfs.WriteStringToFile(pidFileName, pidBody, FileFlags.AutoCreateDirectory);

                Console.WriteLine(ExecMainSignature);

                // The daemon routine is now started. Wait here until InternalStop() is called.
                StoppedEvent.Wait();
            }
            finally
            {
                this.TelnetWatcher._DisposeSafe();
                this.TelnetWatcher = null;

                this.SingleInstance._DisposeSafe();
                this.SingleInstance = null;
            }
        }
Example #13
0
 public static bool WaitProcessExit(int pid, int timeout, CancellationToken cancel = default)
 {
     return(TaskUtil.WaitWithPoll(timeout, 100, () => (IsProcess(pid) == false), cancel));
 }
Example #14
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);
            }
        }
        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");
                }
            }
        }
        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"));
            }
        }