private void ProcessAndPostBytesReceived(byte[] recvBytes) { // load bytes received from the server into InputArray. var inputArray = new InputByteArray(recvBytes); WorkstationCommandList wipCmdList = null; bool badDataLogged = false; while (inputArray.IsEof() == false) { var rv = ParseAndPostInputArray(inputArray, wipCmdList); wipCmdList = rv.Item1; var gotSomething = rv.Item2; // nothing parsed. And there is data remaining. This is an error. if ((gotSomething == false) && (inputArray.IsEof() == false)) { if (badDataLogged == false) { LogBadData(inputArray); badDataLogged = true; } inputArray.GetByte(); // advance by 1 byte in byte stream. } } }
// EndTemp /// <summary> /// parse the byte array as a data stream containing a sequence of SCS control /// functions. ( text data is a /// </summary> /// <param name="InputArray"></param> /// <returns></returns> public static Tuple <ControlFunctionList, string> ParseDataStream(InputByteArray InputArray) { ControlFunctionList funcList = null; string errmsg = null; while (InputArray.IsEof() == false) { // check for IAC EOR var telCode = InputArray.PeekTelnetCommandCode(CommandCode.EOR); if (telCode != null) { break; } var func = ControlFunction.Factory(InputArray); if ((func == null) || (func.Errmsg != null)) { errmsg = "invalid control function. Postion:" + InputArray.Index + " invalid bytes:" + InputArray.PeekToEnd().Head(16).ToHex(' '); break; } if (funcList == null) { funcList = new ControlFunctionList(); } funcList.Add(func); } return(new Tuple <ControlFunctionList, string>(funcList, errmsg)); }
public WriteStructuredFieldCommand(InputByteArray InputArray) : base(InputArray, WorkstationCode.WriteStructuredField) { byte[] buf = null; // advance past the 0x04 and 0xf3. InputArray.AdvanceIndex(2); // first 2 bytes are the LL length bytes. this.llLength = InputArray.PeekBigEndianShort(0); // make sure enough length remaining in the input array if (this.llLength > InputArray.RemainingLength) { this.Errmsg = "LL length " + this.llLength.ToString() + " exceeds remaining length of input array."; } // setup c field and t field if (this.Errmsg == null) { buf = InputArray.GetBytes(this.llLength); this.cField = buf[2]; this.tField = buf[3]; this.RequestCode = this.tField.ToRequestCode(); } if (this.Errmsg == null) { this.BytesLength += this.llLength; this.FormatFlags = null; this.FormatFlags = buf.SubArray(4, 1); } }
public TerminalDataStreamHeader(InputByteArray InputArray) : base(InputArray, "TerminalDataStreamHeader") { // header length should be at least 10 bytes. if ((this.Errmsg == null) && (this.HeaderLength < 10)) { this.Errmsg = "Invalid header length"; } if (this.Errmsg == null) { this.Flags = this.RawBytes.SubArray(7, 2); // flags 16 bits. see page 3 of rfc 1205 // data stream opcode. page 4, rfc 1205 this.OpcodeByte = this.RawBytes[9]; var termCode = this.OpcodeByte.ToTerminalOpcode(); if (termCode == null) { this.Errmsg = "invalid data stream opcode"; } else if (this.VariableLength != 4) { this.Errmsg = "invalid variable header length"; } else { this.TerminalOpcode = termCode.Value; } } }
public static new WriteStructuredFieldOrder Factory(InputByteArray InputArray) { WriteStructuredFieldOrder fieldOrder = null; var buf = InputArray.PeekBytes(10); var wtdOrder = buf[0].ToWtdOrder(); var majorLength = buf.BigEndianBytesToShort(1); var fieldBytes = InputArray.PeekBytes(majorLength + 1); var classByte = buf[3]; var typeByte = buf[4]; if (classByte == 0xd9) { if (typeByte == 0x51) { fieldOrder = new CreateWindowStructuredField(InputArray); } else if (typeByte == 0x60) { fieldOrder = new DrawGridLinesStructuredField(InputArray); } else { throw new Exception("unexpected typeByte"); } } return(fieldOrder); }
/// <summary> /// construct the SBA followed by TextData order pair. /// </summary> /// <param name="InputArray"></param> public LocatedTextDataOrderPair(InputByteArray InputArray) : base(InputArray, "LocatedTextDataOrderPair") { // parse the SBA order. this.SbaOrder = new SetBufferAddressOrder(InputArray); if (this.SbaOrder.Errmsg != null) { this.Errmsg = "SetBufferAddress order error."; } else { this.BytesLength += this.SbaOrder.GetDataStreamLength(); } // text data order. ( this may be empty. ) if (this.Errmsg == null) { this.TextOrder = new TextDataOrder(InputArray); if (this.TextOrder.Errmsg != null) { this.Errmsg = "Text data order error"; } else { this.BytesLength += this.TextOrder.GetDataStreamLength(); } } }
public StartFieldOrder(InputByteArray InputArray) : base(InputArray, WtdOrder.StartField) { if (InputArray.RemainingLength < 8) { this.Errmsg = "Start field order. end of stream."; } if (this.Errmsg == null) { var buf = InputArray.PeekBytes(8); var wtdOrder = buf[0].ToWtdOrder(); this.FFW_Bytes = buf.SubArray(1, 2); this.FCW_Bytes = null; // fcw may or may not be present. if (buf[3] >= 0x80) { this.FCW_Bytes = buf.SubArray(3, 2); this.AttrByte = buf[5]; this.LL_Length = buf.BigEndianBytesToShort(6); this.BytesLength += 7; InputArray.AdvanceIndex(8); } else { this.AttrByte = buf[3]; this.LL_Length = buf.BigEndianBytesToShort(4); this.BytesLength += 5; InputArray.AdvanceIndex(6); } } }
public static Tuple <TerminalVt100Statement, Vt100OutputText> Factory( InputByteArray InputArray) { TerminalVt100Statement stmt = null; Vt100OutputText otStmt = null; var escapeCmd = InputArray.PeekNextByte().ToTelnetCommand(); Vt100Command?cmd = null; if ((escapeCmd != null) && (escapeCmd.Value == TelnetCommand.ESCAPE) && (InputArray.RemainingLength > 1)) { InputArray.AdvanceIndex(1); var rv = InputArray.GetBytesUntilCode(new byte[] { 0x1b }); var buf = rv.Item1; int rx = 0; var stmtText = buf.ToAscii(); stmt = Factory_FromStmtText(stmtText); // process any output text that follows the stmt text. { int lx = stmt.StmtText.Length; if (stmtText.Length > lx) { stmtText = stmtText.Substring(lx); otStmt = new Vt100OutputText(stmtText); } } } return(new Tuple <TerminalVt100Statement, Vt100OutputText>(stmt, otStmt)); }
public TransparentDataOrder(InputByteArray InputArray) : base(InputArray, WtdOrder.TransparentData) { if (InputArray.RemainingLength < 3) { this.Errmsg = "Transparent data order. end of stream."; } if (this.Errmsg == null) { var buf = InputArray.PeekBytes(3); this.LLBytes = buf.SubArray(1, 2); // this is all wrong. was a bug workaround. should instead process the // LLBytes as a big endian length value. // throw new Exception("TransparentDataOrder order does not handle LL length correctly"); // advance past order code and LL bytes. this.BytesLength += 2; InputArray.AdvanceIndex(3); // bytes after the LL byte pair are bytes to show on the display ?? var rv = Common5250.ScanNonTextDataByte(InputArray); int textLx = rv.Item2; this.BytesLength += textLx; this.TransparentData = InputArray.GetEbcdicBytes(textLx); } }
public WorkstationCommandBase(InputByteArray InputArray, WorkstationCode CmdCode) { this.CmdCode = CmdCode; this.InputBytes = InputArray.Bytes; this.BytesStart = InputArray.Index; this.BytesLength = 2; }
ParseByteArray(byte[] ByteArray, int ArrayLx = -1, string DataStreamName = "") { if (ArrayLx == -1) { ArrayLx = ByteArray.Length; } var inputArray = new InputByteArray(ByteArray, ArrayLx); var sessionSettings = new SessionSettings(); var rv = ServerDataStream.ParseDataStream(inputArray, sessionSettings, DataStreamName); var wrkstnCmdList = rv.Item1; var responseItemList = rv.Item2; var dsh = rv.Item3; var telList = rv.Item4; var funcList = rv.Item5; byte[] remainingBytes = null; if (inputArray.RemainingLength > 0) { remainingBytes = inputArray.PeekBytes(); var report = remainingBytes.ToHexReport(16); } return(new Tuple <WorkstationCommandList, ResponseItemList, DataStreamHeader, TelnetCommandList, ControlFunctionList, byte[]>( wrkstnCmdList, responseItemList, dsh, telList, funcList, remainingBytes)); }
public static TelnetSubject?PeekTelnetSubject(this InputByteArray InputArray, int Offset) { var b1 = InputArray.PeekByte(Offset); var subject = b1.ToTelnetSubject(); return(subject); }
public static DataStreamHeader Factory(InputByteArray InputArray) { DataStreamHeader dsHeader = null; if (InputArray.RemainingLength >= 10) { var buf = InputArray.PeekBytes(10); var rcdLgth = buf.BigEndianBytesToShort(0); byte[] rcdType = new byte[2]; Array.Copy(buf, 2, rcdType, 0, 2); byte[] reserved = new byte[2]; Array.Copy(buf, 4, reserved, 0, 2); if ((rcdType[0] == 0x12) && (rcdType[1] == 0xa0) && (rcdLgth >= 10)) { byte varHdrLgth = buf[6]; byte[] flags = new byte[2]; Array.Copy(buf, 7, flags, 0, 2); var dsOpcode = buf[9].ToDataStreamOpcode(); if ((varHdrLgth == 4) && (dsOpcode != null)) { dsHeader = new DataStreamHeader( rcdLgth, rcdType, reserved, varHdrLgth, flags, dsOpcode.Value); InputArray.AdvanceIndex(10); } } } return(dsHeader); }
public TerminalTypeCommand(InputByteArray InputArray, CommandCode CmdCode) : base(InputArray, CmdCode, TelnetSubject.TerminalType) { this.SubOption = null; this.EndFound = false; // statement contains additional parameters. if (this.CmdCode == CommandCode.SB) { var b1 = InputArray.GetNextByte(); this.SubOption = b1.ToTelnetOptionParm(); this.RawBytes.Append(b1); if ((this.SubOption != null) && (this.SubOption.Value == TelnetOptionParm.IS)) { var rv = InputArray.GetBytesUntilCode(new byte[] { 0xff }); this.TerminalNameBytes = rv.Item1; this.RawBytes.Append(this.TerminalNameBytes); } // parse the closing IAC SE ParseClosingSE(InputArray); } }
public ParseStreamBase(InputByteArray InputArray, string ItemName) { this.InputBytes = InputArray.Bytes; this.BytesStart = InputArray.Index; this.BytesLength = 0; this.ItemName = ItemName; }
public ParseStreamBase(InputByteArray InputArray) { this.InputBytes = InputArray.Bytes; this.BytesStart = InputArray.Index; this.BytesLength = 0; this.ItemName = null; }
public static IBM5250DataStreamCommand Factory(InputByteArray InputArray) { IBM5250DataStreamCommand dsCmd = null; if (InputArray.RemainingLength >= 2) { var buf = InputArray.PeekBytes(2); if (buf[0] == 0x04) { var cmdCode = buf[1].ToCommandCode(); if (cmdCode != null) { if (cmdCode.Value == CommandCode.ClearUnit) { dsCmd = new ClearUnitCommand(); } else if (cmdCode.Value == CommandCode.WTD) { dsCmd = WriteToDisplayCommand.Factory(InputArray); } if (dsCmd != null) { InputArray.AdvanceIndex(dsCmd.GetDataStreamLength()); } } } } return(dsCmd); }
public static TextDataOrder Factory(InputByteArray InputArray) { byte? attrByte = null; string displayText = null; // scan forward in the input array for a non text character. int ix = ScanNonTextDataByte(InputArray); int remLx = ix - InputArray.Index; // first byte is the attribute byte. { var b1 = InputArray.PeekByte(0); if ((b1 >= 0x20) && (b1 <= 0x2f)) { attrByte = b1; InputArray.AdvanceIndex(1); remLx -= 1; } } // remaining bytes are text characters in ebcdic. if (remLx > 0) { System.Text.Encoding encoding = System.Text.Encoding.GetEncoding(37); // 37 = ebcdic displayText = InputArray.GetEbcdicBytes(remLx); } TextDataOrder tdOrder = new TextDataOrder(attrByte, displayText); return(tdOrder); }
/// <summary> /// read and return all the bytes to be read from the network stream. /// </summary> /// <param name="Client"></param> /// <param name="NetStream"></param> /// <returns></returns> public static Tuple <InputByteArray, List <string> > ReadInputBlock( TcpClient Client, NetworkStream NetStream, bool ForceRead = false) { InputByteArray inputArray = null; List <string> logList = new List <string>(); if ((NetStream.CanRead == true) && (NetStream.DataAvailable == true)) { var readBuffer = new byte[Client.ReceiveBufferSize]; int readLx = NetStream.Read(readBuffer, 0, Client.ReceiveBufferSize); inputArray = new InputByteArray(readBuffer, readLx); } else if ((NetStream.CanRead == true) && (ForceRead == true)) { logList.Add("==== Force Read ======"); var readBuffer = new byte[Client.ReceiveBufferSize]; int readLx = NetStream.Read(readBuffer, 0, Client.ReceiveBufferSize); inputArray = new InputByteArray(readBuffer, readLx); { var bufText = readBuffer.ToHex(0, readLx, ' '); logList.Add("Read network stream. Num bytes: " + readLx.ToString() + " " + bufText); } } else { inputArray = new InputByteArray(); } return(new Tuple <InputByteArray, List <string> >(inputArray, logList)); }
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)); }
public static TelnetCommand Factory(InputByteArray InputArray, CommandCode CmdCode) { TelnetCommand telnetCmd = null; TelnetSubject?subject = null; if (InputArray.RemainingLength > 2) { subject = InputArray.PeekTelnetSubject(2); } if (CmdCode == CommandCode.SE) { telnetCmd = new EndSubNegCommand(InputArray); } else if (CmdCode == CommandCode.EOR) { telnetCmd = new EOR_Command(InputArray); } else if (subject == null) { telnetCmd = new TelnetCommand(InputArray, CmdCode); } else if (subject.Value == TelnetSubject.NewEnviron) { telnetCmd = new NewEnvironCommand(InputArray, CmdCode); } else if (subject.Value == TelnetSubject.TerminalType) { telnetCmd = new TerminalTypeCommand(InputArray, CmdCode); } else if (subject.Value == TelnetSubject.END_OF_RECORD) { telnetCmd = new EndOfRecordStatement(InputArray, CmdCode); } else if (subject.Value == TelnetSubject.TRANSMIT_BINARY) { telnetCmd = new TransmitBinaryCommand(InputArray, CmdCode); } else if (subject.Value == TelnetSubject.NAWS) { telnetCmd = new NawsStatement(InputArray, CmdCode); } else if (subject.Value == TelnetSubject.ECHO) { throw new Exception("echo subject of " + CmdCode.ToString() + " command."); } else { throw new Exception("Unexpect telnet command"); } return(telnetCmd); }
public Query5250Response(InputByteArray InputArray) { InputByteArray buf = null; if (InputArray.RemainingLength < 58) { this.Errmsg = "Insufficient bytes in byte stream for 5250 query response."; } if (this.Errmsg == null) { this.Length = InputArray.PeekBigEndianShort(0); if (InputArray.RemainingLength < this.Length) { this.Errmsg = "response length exceeds byte stream."; } } if (this.Errmsg == null) { this.RawBytes = InputArray.PeekBytes(this.Length); buf = new InputByteArray(this.RawBytes); buf.AdvanceIndex(2); // the length this.cField = buf.GetByte(); var tField = buf.GetByte(); this.RequestCode = tField.ToRequestCode(); this.ResponseByte = buf.GetByte(); // 0x80 fixed code if ((cField != 0xd9) || (this.RequestCode == null) || (this.ResponseByte != 0x80)) { this.Errmsg = "invalid c Field, t Field or response byte in 5250 " + "query response."; } } // isolate other 5250 query response fields. if (this.Errmsg == null) { this.ControlUnitCode = buf.GetBytes(2); this.CodeLevel = buf.GetBytes(3); this.Reserve1 = buf.GetBytes(16); this.WorkstationByte = buf.GetByte(); this.MachineType = buf.GetEbcdicBytes(7); this.KeyboardId = buf.GetByte(); buf.AdvanceIndex(2); this.SerialNumber = buf.GetBytes(4); this.MaxInputFields = buf.GetBigEndianShort(); this.Reserve2 = buf.GetBytes(3); this.Capabilities = buf.GetBytes(5); } // is a valid query 5250 response byte stream. Advance index of input bytes. if (this.Errmsg == null) { InputArray.AdvanceIndex(this.Length); } }
public CreateWindowStructuredField(InputByteArray InputArray) : base(InputArray) { this.FlagByte1 = this.FieldBytes[5]; this.FlagByte2 = this.FieldBytes[6]; this.NumRow = (int)this.FieldBytes[8]; this.NumCol = (int)this.FieldBytes[9]; }
public TelnetCommand(InputByteArray InputArray, CommandCode CmdCode) { this.Start = InputArray.Index; this.RawBytes = new ByteArrayBuilder(); this.RawBytes.Append(InputArray.GetBytes(2)); this.EscapeCode = CommandCode.IAC; this.CmdCode = CmdCode; }
public static WorkstationCommandBase ParseFactory(InputByteArray InputArray) { WorkstationCommandBase dsCmd = null; if (InputArray.RemainingLength >= 2) { // command codes as documented on 15.2 - 1 of 5494 function ref manual var buf = InputArray.PeekBytes(2); if (buf[0] == 0x04) { var wrkstnCode = buf[1].ToWorkstationCode(); if (wrkstnCode != null) { var code = wrkstnCode.Value; if (code == WorkstationCode.ClearUnit) { dsCmd = new ClearUnitCommand(InputArray); } else if (code == WorkstationCode.WTD) { dsCmd = new WriteToDisplayCommand(InputArray); } else if (code == WorkstationCode.ReadMdtFields) { dsCmd = new ReadMdtFieldsCommand(InputArray); } // 04 F3. write structure field. Used as vehicle for the D9 70 5250 query // command. else if (code == WorkstationCode.WriteStructuredField) { dsCmd = new WriteStructuredFieldCommand(InputArray); } else if (code == WorkstationCode.SaveScreen) { dsCmd = new SaveScreenCommand(InputArray); } else if (code == WorkstationCode.RestoreScreen) { dsCmd = new RestoreScreenCommand(InputArray); } else { throw new Exception( "workstation data stream command code not supported. " + code.ToString()); } } } } return(dsCmd); }
public WtdOrderBase(InputByteArray InputArray, WtdOrder?OrderCode) : base(InputArray, OrderCode == null ? "" : OrderCode.Value.ToItemName( )) { this.OrderCode = OrderCode; if (this.OrderCode != null) { this.BytesLength = 1; } }
public WriteToDisplayCommand(InputByteArray InputArray) : base(InputArray, WorkstationCode.WTD) { this.OrderList = new List <WtdOrderBase>(); if (InputArray.RemainingLength < 4) { this.Errmsg = "Byte stream too short. Missing control chars."; } if (this.Errmsg == null) { var buf = InputArray.PeekBytes(4); this.ControlChars = buf.SubArray(2, 2); InputArray.AdvanceIndex(4); this.BytesLength = 4; // gather WTD orders and display characters. while (true) { WtdOrderBase orderBase = null; if (InputArray.RemainingLength == 0) { break; } orderBase = WtdOrderBase.Factory(InputArray); // not an explicit WTD order. Check that is a text data order. if (orderBase == null) { var b1 = InputArray.PeekByte(0); if (Common5250.IsTextDataChar(b1) == true) { orderBase = new TextDataOrder(InputArray); } } // current input stream bytes are not WTD order. End of WTD command. if (orderBase == null) { break; } // got an order but some sort of form error. if (orderBase.Errmsg != null) { throw new Exception("invalid WTD order"); } // Append to list of orders of the WTD command. this.OrderList.Add(orderBase); this.BytesLength += orderBase.GetDataStreamLength(); } } }
public TextDataOrder(InputByteArray InputArray) : base(InputArray, "TextData") { var b1 = InputArray.PeekByte(0); if (Common5250.IsTextDataChar(b1) == false) { this.Errmsg = "Invalid text data order. Order must begin with data character."; } if (this.Errmsg == null) { // scan forward in the input array for a non text character. var rv = Common5250.ScanNonTextDataByte(InputArray); this.DataStreamLength = rv.Item2; // the actual data stream bytes. var rawBytes = InputArray.PeekBytes(this.DataStreamLength); int rawLx = rawBytes.Length; // first byte is the attribute byte. if (Common5250.IsAttributeByte(b1)) { this.AttrByte = b1; } // last text byte is an attribute byte. if ((rawLx > 1) && (rawBytes[rawLx - 1].IsAttributeByte( ) == true)) { this.TailAttrByte = rawBytes[rawLx - 1]; } // bytes the attrByte and tailAttrByte are textBytes. { int fx = 0; int lx = rawLx; if (this.AttrByte != null) { fx += 1; lx -= 1; } if (this.TailAttrByte != null) { lx -= 1; } if (lx > 0) { this.TextBytes = rawBytes.SubArray(fx, lx); } } this.RawBytes = rawBytes; this.BytesLength = rawLx; InputArray.AdvanceIndex(rawLx); } }
/// <summary> /// return the datastreamcode from the input stream. /// </summary> /// <param name="InputArray"></param> /// <returns></returns> public static DataStreamCode?PeekDataStreamCode(this InputByteArray InputArray) { DataStreamCode?code = null; var buf = InputArray.PeekBytesLenient(7); if ((buf[2] == 0x12) && (buf[3] == 0xa0)) { code = buf.SubArray(4, 2).ToDataStreamCode(); } return(code); }
/// <summary> /// expecting closing IAC SE command code. If exists at current position of the /// input array, process the IAC SE command. /// </summary> /// <param name="InputArray"></param> protected void ParseClosingSE(InputByteArray InputArray) { // parse the closing IAC SE var seCode = InputArray.PeekTelnetCommandCode(CommandCode.SE); if (seCode != null) { this.GotClosingSE = true; this.RawBytes.Append(InputArray.GetBytes(2)); } }