public static Tuple <List <ShowItemBase>, TelnetLogList> NextServerRequest(
            NetworkStreamBackedInputByteArray InputArray,
            NegotiateSettings NegotiateSettings,
            bool ForceRead = false)
        {
            TelnetLogList logList      = new TelnetLogList();
            var           showItemList = new ShowItemList();

            while (true)
            {
                // read available bytes from input stream.
                if (InputArray.IsEof())
                {
                    var log = InputArray.ReadFromNetworkStream(5, 5, ForceRead);
                    logList.AddItems(log);
                }

                // no input data to process.
                if (InputArray.IsEof())
                {
                    break;
                }

                var buf = InputArray.PeekDataStreamHeader();
                if (buf != null)
                {
                    var dsh = new DataStreamHeader(InputArray);
                    logList.AddItems(Direction.Read, dsh.ToReportLines( ), true);

                    var rv = ParseAndProcessWorkstationCommand(InputArray, dsh);
                    var workstationCommand = rv.Item1;
                    showItemList = rv.Item2;
                    logList.AddItems(rv.Item4);
                }

                // check for IAC EOR
                {
                    var telCode = InputArray.PeekTelnetCommandCode(CommandCode.EOR);
                    if (telCode != null)
                    {
                        var telCmd = InputArray.NextTelnetCommand();
                        logList.AddItems(Direction.Read, telCmd.ToReportLines(), true);
                    }
                }

                // peek and process input bytes as a telnet stmt. ( starts with IAC )
                {
                    var telCmd = InputArray.NextTelnetCommand();
                    if (telCmd != null)
                    {
                        var rv         = TelnetConnection.ProcessTelnetCommand(telCmd, NegotiateSettings);
                        var cx         = rv.Item1;
                        var writeBytes = rv.Item2;
                        logList.AddItems(rv.Item3);
                        WriteToHost(logList, writeBytes, InputArray.NetStream);
                    }
                }
            }
            return(new Tuple <List <ShowItemBase>, TelnetLogList>(showItemList, logList));
        }
        public static Tuple <WorkstationCommandList, TelnetLogList> GetAndParseWorkstationCommandList(
            NetworkStreamBackedInputByteArray InputArray,
            SessionSettings SessionSettings)
        {
            TelnetLogList logList       = new TelnetLogList();
            var           wrkstnCmdList = new WorkstationCommandList();

            var dsh = new DataStreamHeader(InputArray);

            if (dsh != null)
            {
                logList.AddItems(Direction.Read, dsh.ToReportLines( ), true);
            }

            if ((dsh != null) && (dsh.Errmsg == null))
            {
                bool lastCmdWasTelnet_EOR = false;
                while (dsh != null)
                {
                    // read available bytes from input stream.
                    if (InputArray.IsEof() && (lastCmdWasTelnet_EOR == false))
                    {
                        var log = InputArray.ReadFromNetworkStream(5, 5);
                        logList.AddItems(log);
                    }

                    // no input data to process.
                    if (InputArray.IsEof())
                    {
                        break;
                    }
                    lastCmdWasTelnet_EOR = false;

                    // check for IAC EOR
                    var telCode = InputArray.PeekTelnetCommandCode(CommandCode.EOR);
                    if (telCode != null)
                    {
                        var telCmd = InputArray.NextTelnetCommand();
                        logList.AddItems(Direction.Read, telCmd.ToReportLines(), true);
                        lastCmdWasTelnet_EOR = true;
                    }

                    // process the input as workstation data stream commands.
                    else
                    {
                        var rv = ParseAndProcessWorkstationCommand(InputArray, dsh);
                        var workstationCommand = rv.Item1;
                        dsh = rv.Item3;
                        logList.AddItems(rv.Item4);

                        if (workstationCommand != null)
                        {
                            wrkstnCmdList.Add(workstationCommand);
                        }
                    }
                }
            }
            return(new Tuple <WorkstationCommandList, TelnetLogList>(wrkstnCmdList, logList));
        }
        private void butParseResponse_Click(object sender, RoutedEventArgs e)
        {
            var logList = new TelnetLogList();

            var text  = TextBox1.Text;
            var lines = text.Split(
                new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
            var ba = ParseHexLines(lines);

            Process5250.ParseResponseStream(logList, ba);

            foreach (var item in logList)
            {
                if (item.NewGroup == true)
                {
                    this.Model.RunLog.Add("");
                }
                this.Model.RunLog.Add(item.Text);
            }

            // print the bytes of the response stream as lines of hex text.
            {
                var rep = ba.ToHexReport(16);
                logList.AddItem(Direction.Read, "Length:" + ba.Length + " Byte stream bytes:");
                logList.AddItems(Direction.Read, rep);
            }
        }
        ParseAndProcessWorkstationCommand(
            InputByteArray inputArray, DataStreamHeader StreamHeader)
        {
            var logList = new TelnetLogList();
            WorkstationCommandBase wrkstnCommand           = null;
            DataStreamHeader       currentDataStreamHeader = StreamHeader;
            ShowItemList           showItemList            = null;

            wrkstnCommand = WorkstationCommandBase.ParseFactory(inputArray);
            if (wrkstnCommand == null)
            {
                currentDataStreamHeader = null;
            }
            else
            {
                logList.AddItems(Direction.Read, wrkstnCommand.ToReportLines(), true);

                // process WriteToDisplay command. This command contains a list TextData and
                // start field orders. Create ShowItemList items from those orders.
                if (wrkstnCommand is WriteToDisplayCommand)
                {
                    var wtdCommand = wrkstnCommand as WriteToDisplayCommand;
                    showItemList = wtdCommand.BuildShowItemList(logList);
                }
            }
            return(new Tuple <WorkstationCommandBase, ShowItemList, DataStreamHeader, TelnetLogList>(
                       wrkstnCommand, showItemList, currentDataStreamHeader, logList));
        }
        /// <summary>
        /// parse the 5250 data stream that is sent from the client to the server.
        /// </summary>
        /// <param name="LogFile"></param>
        /// <param name="ToServerStream"></param>
        /// <returns></returns>
        public static Tuple <object[], string> ParseResponseStream(
            TelnetLogList LogList, byte[] ResponseStream)
        {
            List <object> listItems = new List <object>();
            string        errmsg    = null;

            var inputArray =
                new NetworkStreamBackedInputByteArray(ResponseStream, ResponseStream.Length);
            var writeStream                 = new ByteArrayBuilder();
            DataStreamHeader dsHeader       = null;
            ResponseHeader   responseHeader = null;

            // stream starts with data stream header.
            dsHeader = new DataStreamHeader(inputArray);
            listItems.Add(dsHeader);
            errmsg = dsHeader.Errmsg;
            LogList.AddItems(Direction.Write, dsHeader.ToReportLines(), true);

            // next is the response header.
            if (errmsg == null)
            {
                responseHeader = new ResponseHeader(inputArray);
                listItems.Add(responseHeader);
                errmsg = responseHeader.Errmsg;
                LogList.AddItems(Direction.Write, responseHeader.ToReportLines(), true);
            }

            // repeating instances of sbaOrder, textDataOrder pairs.
            while (true)
            {
                // check that an SBA order is starting. Leave loop when it is not.
                if (SetBufferAddressOrder.CheckOrder(inputArray) != null)
                {
                    break;
                }

                var orderPair = new LocatedTextDataOrderPair(inputArray);
                if (orderPair.Errmsg != null)
                {
                    break;
                }
                listItems.Add(orderPair);
                LogList.AddItems(Direction.Write, orderPair.ToReportLines(), true);
            }

            return(new Tuple <object[], string>(listItems.ToArray(), errmsg));
        }
        void NewParse()
        {
            var logList = new TelnetLogList();

            var text  = TextBox1.Text;
            var lines = text.Split(
                new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
            var ba              = ParseHexLines(lines);
            var inputArray      = new NetworkStreamBackedInputByteArray(ba, ba.Length);
            var sessionSettings = new SessionSettings();

            Process5250.ParseResponseStream(logList, ba);

            foreach (var item in logList)
            {
                if (item.NewGroup == true)
                {
                    this.Model.RunLog.Add("");
                }
                this.Model.RunLog.Add(item.Text);
            }


            // peek at the input stream from server. Classify the data that is next
            // to receive.
            var typeData = ServerDataStream.PeekServerCommand(inputArray);

            // input data not recogizied. Not a 5250 data strem header.
            if (typeData == null)
            {
                logList.AddItem(Direction.Read, "Unknown data stream data");
                logList.AddItems(
                    Direction.Read, inputArray.PeekBytes().ToHexReport(16));
            }

            else if (typeData.Value == TypeServerData.workstationHeader)
            {
                {
                    var rv = Process5250.GetAndParseWorkstationCommandList(
                        inputArray, sessionSettings);

                    var workstationCmdList = rv.Item1;
                    logList.AddItems(rv.Item2);
                }
            }
        }
        public TelnetLogList ParseDataStream(
            NetworkStreamBackedInputByteArray inputArray, SessionSettings sessionSettings)
        {
            var logList = new TelnetLogList();

            bool didParse = true;

            while ((didParse == true) && (inputArray.RemainingLength > 0))
            {
                didParse = false;

                if (didParse == false)
                {
                    var telCmd = inputArray.NextTelnetCommand();
                    if (telCmd != null)
                    {
                        var s1 = telCmd.ToString();
                        logList.AddItem(Direction.Read, s1);
                        didParse = true;
                    }
                }

                if (didParse == false)
                {
                    var rv = Process5250.GetAndParseWorkstationCommandList(
                        inputArray, sessionSettings);

                    logList.AddItems(rv.Item2);
                    var wrkstnCmdList = rv.Item1;

                    // draw the fields and literals on the canvas.
                    if (wrkstnCmdList?.Count > 0)
                    {
                        didParse = true;
                        foreach (var workstationCmd in wrkstnCmdList)
                        {
                        }
                    }
                }
            }
            return(logList);
        }
        ProcessWorkstationDataStream(
            this ConnectedSocketPack SocketPack, ScreenVisualItems VisualItems,
            CanvasPositionCursor Caret)
        {
            WorkstationCommandList       workstationCmdList = null;
            List <WriteToDisplayCommand> wtdCmdList         = null;
            DataStreamHeader             dsh = null;
            var           returnCmdList      = new WorkstationCommandList();
            HowReadScreen?howRead            = null;
            var           logList            = new TelnetLogList();
            bool          gotEOR             = false;

            while (gotEOR == false)
            {
                // input array is eof. Exit loop if have read a READ workstn command.
                // Otherwise, read from server.
                if (SocketPack.InputArray.IsEof() == true)
                {
                    if (howRead != null)
                    {
                        break;
                    }
                    {
                        var log = SocketPack.InputArray.ReadFromNetworkStream(10, 60);
                        logList.AddItems(log);
                        if (SocketPack.InputArray.IsEof() == true)
                        {
                            break;
                        }
                    }
                }

                // peek at the input stream from server. Classify the data that is next
                // to receive.
                var typeData = ServerDataStream.PeekServerCommand(SocketPack.InputArray);

                // input data not recogizied. Not a 5250 data strem header.
                if (typeData == null)
                {
                    logList.AddItem(Direction.Read, "Unknown data stream data");
                    logList.AddItems(
                        Direction.Read, SocketPack.InputArray.PeekBytes().ToHexReport(16));
                    break;
                }

                if (typeData.Value == TypeServerData.workstationHeader)
                {
                    {
                        var rv = Process5250.GetAndParseWorkstationCommandList(
                            SocketPack.InputArray, SocketPack.Settings);
                        dsh = rv.Item1;
                        workstationCmdList = rv.Item2;
                        logList.AddItems(rv.Item3);
                        gotEOR = rv.Item4;
                    }

                    foreach (var workstationCmd in workstationCmdList)
                    {
                        if (workstationCmd is ClearUnitCommand)
                        {
                            returnCmdList.Add(workstationCmd);
                        }

                        // WTD command. Add to list of WTD commands. This list is returned to the
                        // caller of this method.
                        else if (workstationCmd is WriteToDisplayCommand)
                        {
                            returnCmdList.Add(workstationCmd);
                            var wtdCommand = workstationCmd as WriteToDisplayCommand;
                            if (wtdCmdList == null)
                            {
                                wtdCmdList = new List <WriteToDisplayCommand>();
                            }
                            wtdCmdList.Add(wtdCommand);
                        }

                        else if (workstationCmd is ReadMdtFieldsCommand)
                        {
                            howRead = HowReadScreen.ReadMdt;
                        }

                        // save screen command. Build response, send back to server.
                        else if (workstationCmd is SaveScreenCommand)
                        {
                            var ra = SaveScreenCommandExt.BuildSaveScreenResponse(VisualItems, Caret);

                            // send response stream back to server.
                            {
                                TelnetConnection.WriteToHost(logList, ra, SocketPack.TcpStream);
                                gotEOR = false;
                            }
                        }

                        else if (workstationCmd is WriteStructuredFieldCommand)
                        {
                            var wsfCmd = workstationCmd as WriteStructuredFieldCommand;
                            if (wsfCmd.RequestCode == WSF_RequestCode.Query5250)
                            {
                                var ra = Query5250Response.BuildQuery5250Response();

                                // send response stream back to server.
                                {
                                    TelnetConnection.WriteToHost(logList, ra, SocketPack.TcpStream);
                                    gotEOR = false;
                                }
                            }
                        }
                        else if (workstationCmd is WriteSingleStructuredFieldCommand)
                        {
                        }
                    }
                }
            }
            return(new Tuple <HowReadScreen?, List <WriteToDisplayCommand>,
                              TelnetLogList, WorkstationCommandList, DataStreamHeader, bool>(
                       howRead, wtdCmdList, logList, returnCmdList, dsh, gotEOR));
        }
        private void MenuItem_Click(object sender, RoutedEventArgs e)
        {
            string itemText = null;

            if (sender is MenuItem)
            {
                itemText = (sender as MenuItem).Header as string;
            }

            if (itemText == "Test")
            {
                var logList     = new TelnetLogList();
                var negSettings = NegotiateSettings.Build5250Settings("SRICHTER", "Steve25");

                var lines = System.IO.File.ReadAllLines("c:\\downloads\\hextext.txt");
                var ba    = ParseHexLines(lines);

                // print the bytes of the response stream as lines of hex text.
                {
                    var rep = ba.ToHexReport(16);
                    logList.AddItem(Direction.Read, "Length:" + ba.Length + " Byte stream bytes:");
                    logList.AddItems(Direction.Read, rep);
                }

                var inputArray      = new NetworkStreamBackedInputByteArray(ba, ba.Length);
                var sessionSettings = new SessionSettings();

                var rv = Process5250.GetAndParseWorkstationCommandList(
                    inputArray, sessionSettings);

                logList.AddItems(rv.Item2);
                var wrkstnCmdList = rv.Item1;

                // draw the fields and literals on the canvas.
                if (wrkstnCmdList != null)
                {
                    foreach (var workstationCmd in wrkstnCmdList)
                    {
                    }
                }

                foreach (var item in logList)
                {
                    this.Model.RunLog.Add(item.Text);
                }

                return;
            }

            else if (itemText == "Parse server stream")
            {
                var text  = TextBox1.Text;
                var lines = text.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);

                var ba = ParseHexLines(lines);

                // print the bytes of the response stream as lines of hex text.
                {
                    TelnetLogList logList = new TelnetLogList();
                    var           rep     = ba.ToHexReport(16);
                    logList.AddItem(Direction.Read, "Length:" + ba.Length + " Byte stream bytes:");
                    logList.AddItems(Direction.Read, rep);
                }
            }

            else if (itemText == "Parse response stream")
            {
                var logList     = new TelnetLogList();
                var negSettings = NegotiateSettings.Build5250Settings("SRICHTER", "Steve25");

                var lines = System.IO.File.ReadAllLines("c:\\downloads\\hextext.txt");
                var ba    = ParseHexLines(lines);

                // print the bytes of the response stream as lines of hex text.
                {
                    var rep = ba.ToHexReport(16);
                    logList.AddItem(Direction.Read, "Length:" + ba.Length + " Byte stream bytes:");
                    logList.AddItems(Direction.Read, rep);
                }

                Process5250.ParseResponseStream(logList, ba);

                foreach (var item in logList)
                {
                    if (item.NewGroup == true)
                    {
                        this.Model.RunLog.Add("");
                    }
                    this.Model.RunLog.Add(item.Text);
                }

                return;
            }

            else if (itemText == "Exit")
            {
                this.Close();
            }

            else if (itemText == "Settings")
            {
            }

            else if (itemText == "Print")
            {
                LinePrinter.PrintLines(this.Model.RunLog);
            }
            else if (itemText == "Clear log")
            {
                Model.RunLog.Clear();
            }
        }
        public static Tuple <int, int, List <ShowItemBase>, TelnetLogList> GetAndProcessStream(
            TcpClient Client, NetworkStream NetStream,
            NetworkStreamBackedInputByteArray InputArray,
            NegotiateSettings NegotiateSettings,
            bool ForceRead = false)
        {
            int  sendStmtCx   = 0;
            int  getStmtCx    = 0;
            var  logList      = new TelnetLogList();
            var  showItemList = new ShowItemList();
            bool exitLoop     = false;

            while (exitLoop == false)
            {
                // read available bytes from input stream.
                if (InputArray.IsEof())
                {
                    var log = InputArray.ReadFromNetworkStream(5, 5, ForceRead);
                    logList.AddItems(log);
                }

                // no input data to process.
                if (InputArray.IsEof())
                {
                    break;
                }

                DataStreamHeader currentDataStreamHeader = null;
                while (true)
                {
                    if (InputArray.IsEof() == true)
                    {
                        break;
                    }

                    // process the input as 5250 data stream commands.
                    if (currentDataStreamHeader != null)
                    {
                        var rv = ParseAndProcessWorkstationCommand(InputArray, currentDataStreamHeader);
                        var workstationCommand = rv.Item1;
                        showItemList            = rv.Item2;
                        currentDataStreamHeader = rv.Item3;
                        logList.AddItems(rv.Item4);
                        continue;
                    }

                    // peek and process input bytes as a telnet stmt. ( starts with IAC )
                    var telCmd = InputArray.NextTelnetCommand();
                    if (telCmd != null)
                    {
                        getStmtCx += 1;

                        var rv         = TelnetConnection.ProcessTelnetCommand(telCmd, NegotiateSettings);
                        var cx         = rv.Item1;
                        var writeBytes = rv.Item2;
                        logList.AddItems(rv.Item3);
                        sendStmtCx += cx;
                        WriteToHost(logList, writeBytes, NetStream);

                        continue;
                    }

                    var dsh = new DataStreamHeader(InputArray);
                    if ((dsh != null) && (dsh.Errmsg == null))
                    {
                        logList.AddItem(Direction.Read, dsh.ToString());
                        currentDataStreamHeader = dsh;
                        continue;
                    }
                    exitLoop = true;
                    break;
                }
            }
            return(new Tuple <int, int, List <ShowItemBase>, TelnetLogList>(
                       getStmtCx, sendStmtCx, showItemList, logList));
        }