public static List <TelnetPacket> Parse(byte[] data, out byte[] remaining) { List <TelnetPacket> list = new List <TelnetPacket>(); if (BufUtil.CountDelim(data, IAC) > 0) { List <byte[]> seq = BufUtil.SplitIAC(data, IAC, out byte[] unparsed); remaining = unparsed; seq.ForEach(s => { switch (s[1]) { case Command.DO: case Command.DONT: case Command.WILL: case Command.WONT: list.Add(new TelnetPacket { Command = s[1], Option = s[2] }); break; case Command.SB: byte[] payload = new byte[s.Length - 3]; Buffer.BlockCopy(s, 3, payload, 0, payload.Length); list.Add(new TelnetPacket { Command = s[1], Option = s[2], Payload = payload }); break; case Command.SE: // Ignore sub-negotiation end. break; } }); } else { remaining = data; } return(list); }
public bool CanConsume() { return(InternalBuffer != null && InternalBuffer.Length > 0 && BufUtil.HasEOL(InternalBuffer)); }
public XeonClient(TcpClient client) { Client = client; RemoteEndPoint = Client.Client.RemoteEndPoint.ToString(); Stream = Client.GetStream(); // Handle Telnet events internally first. OnTelnet += (packet) => { switch (packet.Command) { case Telnet.Command.SB: switch (packet.Option) { case Telnet.Option.GMCP: GMCP.GmcpData gmcp = GMCP.GmcpData.FromTelnetPacket(packet); InvokeOnGMCP(gmcp); break; default: InvokeOnTelnetSB(packet); break; } break; case Telnet.Command.WILL: if (!IsWaitingOn(packet.Option)) { // Client initiated SetOption(packet.Option, Telnet.TelnetOptionState.Waiting); InvokeOnTelnetWill(packet.Option); } else { // Server initiated. SetOption(packet.Option, Telnet.TelnetOptionState.Enabled); } break; case Telnet.Command.WONT: if (!IsWaitingOn(packet.Option)) { // Client initiated SetOption(packet.Option, Telnet.TelnetOptionState.Waiting); InvokeOnTelnetWont(packet.Option); } else { // Server initiated. SetOption(packet.Option, Telnet.TelnetOptionState.Disabled); } break; case Telnet.Command.DO: if (!IsWaitingOn(packet.Option)) { // Client initiated SetOption(packet.Option, Telnet.TelnetOptionState.Waiting); InvokeOnTelnetDo(packet.Option); } else { // Server initiated. SetOption(packet.Option, Telnet.TelnetOptionState.Enabled); } break; case Telnet.Command.DONT: if (!IsWaitingOn(packet.Option)) { // Client initiated SetOption(packet.Option, Telnet.TelnetOptionState.Waiting); InvokeOnTelnetDont(packet.Option); } else { // Server initiated. SetOption(packet.Option, Telnet.TelnetOptionState.Disabled); } break; default: InvokeOnTelnetUnhandled(packet); break; } }; Task t = new Task(async() => { while (true) { try { Client.Client.Send(new byte[1], 0); int bytesRead = 0; while (Stream.DataAvailable) { buffer = new byte[1024]; int localBytes = await Stream.ReadAsync(buffer, 0, buffer.Length); bytesRead += localBytes; if (buffer.Length > localBytes) { byte[] temp = new byte[localBytes]; Buffer.BlockCopy(buffer, 0, temp, 0, localBytes); buffer = temp; } ClientBuffer.Add(buffer); if (BufUtil.CountDelim(ClientBuffer.InternalBuffer, Telnet.IAC) > 0) { List <Telnet.TelnetPacket> packets = Telnet.Parse(ClientBuffer.InternalBuffer, out byte[] remaining); ClientBuffer = new BufferBuilder(); packets.ForEach(packet => { InvokeOnTelnet(packet); }); if (remaining.Length > 0) { ClientBuffer.Add(remaining); } } } if (ClientBuffer.CanConsume()) { byte[] buf = BufUtil.StripEOL(ClientBuffer.Consume()); ClientBuffer = new BufferBuilder(); string data = Encoding.UTF8.GetString(buf); InvokeOnMessage(data); } } catch (SocketException) { break; } } Client.Close(); InvokeOnDisconnect(); }); t.Start(); }