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);
        }
 public TelnetLocalLogWatcher(TelnetStreamWatcherOptions options) : base(options)
 {
 }