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));
        }
        /// <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));
        }