/**
        /// <summary>
        /// The main entry point for the application.
        /// Can be used to test the programm and run it from command line.
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
            const string SEH = "--- screen ends here ---";
            // coordinates are 0,0 based since we do not specify anything
            VirtualScreen vs = new VirtualScreen(80, 40);
            // simple fill
            VirtualScreenTest.FillScreen(vs);
            Console.WriteLine(vs.Hardcopy());
            Console.WriteLine(SEH);
            Console.ReadLine();
            // deleting of an area
            vs.CleanScreen(4,4,75,35);
            Console.WriteLine(vs.Hardcopy());
            Console.WriteLine(SEH);
            Console.ReadLine();
            // scrolling
            vs.ScrollUp(2);
            Console.WriteLine(vs.Hardcopy());
            Console.WriteLine(SEH);
            Console.ReadLine();
            // block operations (write to screen)
            VirtualScreenTest.WriteBlockOperation(vs);
            Console.WriteLine(vs.Hardcopy());
            Console.WriteLine(SEH);
            Console.ReadLine();
            // cursor movements
            VirtualScreenTest.WriteBigX(vs);
            Console.WriteLine(vs.Hardcopy());
            Console.WriteLine(SEH);
            Console.ReadLine();

        } // main

        **/
        /// <summary>
        /// Fill the screen with a pattern
        /// </summary>
        /// <param name="vs">Virtual screen</param>
        public static void FillScreen(VirtualScreen vs)
        {
            byte w = 48; // 48=0 57=9
            for (int y = 0; y < vs.Height; y++)
            {
                w = 48;
                for (int x = 0; x < vs.Width; x++)
                {
                    vs.WriteByte(w);
                    if (w<57)
                        w++;
                    else
                        w = 48;
                }
            }
        }
        /// <summary>
        /// Connect to the telnet server
        /// </summary>
        /// <returns>true if connection was successful</returns>
        public bool Connect()
        {
            // check for buffer
            if (this.buffer==null)
                this.buffer = new byte[RECEIVEBUFFERSIZE];

            // virtual screen
            if (this.virtualScreen==null)
                this.virtualScreen = new VirtualScreen(this.vsWidth, this.vsHeight, 1, 1);

            // set the callbacks
            if (this.callBackReceive==null)
                this.callBackReceive = new AsyncCallback(ReadFromStream);
            if (this.callBackSend==null)
                this.callBackSend = new AsyncCallback(WriteToStream);

            // flags
            this.serverEcho = false;
            this.clientInitNaws = false;
            this.firstResponse = true;
            this.nawsNegotiated = false;
            this.forceLogout = false;

            // return physical connection
            if (this.tcpClient!=null)
                return true; // we still have a connection -> ?? better reconnect ??
            else
            {
                try
                {
                    // TODO: Improve performance ...?
                    // This is not working:	IPAddress ipAddress = IPAddress.Parse(this.hostName);
                    //						IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, this.port);
                    // because it addresses local endpoints
                    this.tcpClient = new TcpClient(this.hostName, this.port);
                    this.tcpClient.ReceiveTimeout = this.timeoutReceive;
                    this.tcpClient.SendTimeout = this.timeoutSend;
                    this.tcpClient.NoDelay = true;
                    this.tcpClient.GetStream().BeginRead(this.buffer, 0, this.buffer.Length, this.callBackReceive, null);
                    return true;
                }
                catch
                {
                    this.tcpClient = null;
                    return false;
                }
            }
        }
        /// <summary>
        /// Closes external resources.
        /// Safe, can be called multiple times
        /// </summary>
        public void Close()
        {
            // physical connection
            if (this.tcpClient!=null)
            {
                try
                {
                    if (this.tcpClient.GetStream() != null)
                    {
                        // it is important to close the stream
                        // because somehow tcpClient does not physically breaks down
                        // the connection - on "one connection" telnet server the
                        // server remains blocked if not doing it!
                        try
                        {
                            this.tcpClient.GetStream().Close();
                        }
                        catch
                        {
                            // further handling would go here
                        }
                    }
                    this.tcpClient.Close();
                    this.tcpClient = null;
                }
                catch
                {
                    this.tcpClient = null;
                }
            }

            // clean up
            // fast, "can be done several" times
            this.virtualScreen = null;
            this.buffer = null;
            this.callBackReceive = null;
            this.callBackSend = null;
            this.forceLogout = false;
        }
        /// <summary>
        /// Connect to the ssh server
        /// </summary>
        /// <returns>true if connection was successful</returns>
        public bool Connect()
        {
            // check for buffer
            if (this.buffer == null)
            {
                this.buffer = new byte[RECEIVEBUFFERSIZE];
            }

            // virtual screen
            if (_virtualScreen == null)
            {
                _virtualScreen = new VirtualScreen(this.vsWidth, this.vsHeight, 1, 1);
            }

            /*
             * // set the callbacks
             * if (this.callBackReceive == null)
             *  this.callBackReceive = new AsyncCallback(ReadFromStream);
             * if (this.callBackSend == null)
             *  this.callBackSend = new AsyncCallback(WriteToStream);
             */
            // flags
            this.serverEcho     = false;
            this.clientInitNaws = false;
            this.firstResponse  = true;
            this.nawsNegotiated = false;
            this.forceLogout    = false;

            //Open SSH-Connection
            Granados.SSHConnectionParameter f = new Granados.SSHConnectionParameter();
            f.EventTracer = new Tracer(); //to receive detailed events, set ISSHEventTracer
            Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            f.Protocol = Granados.SSHProtocol.SSH2; //this sample works on both SSH1 and SSH2
            string host_ip = hostName;

            f.UserName = userName;
            string password = Password;

            s.Connect(new IPEndPoint(IPAddress.Parse(host_ip), port)); //22 is the default SSH port

            //former algorithm is given priority in the algorithm negotiation
            f.PreferableHostKeyAlgorithms = new PublicKeyAlgorithm[] { PublicKeyAlgorithm.RSA, PublicKeyAlgorithm.DSA };
            f.PreferableCipherAlgorithms  = new Granados.CipherAlgorithm[] { Granados.CipherAlgorithm.Blowfish, Granados.CipherAlgorithm.TripleDES };
            f.WindowSize     = 0x1000;       //this option is ignored with SSH1
            reader           = new Reader(); //simple event receiver
            reader.parentObj = this;

            Granados.AuthenticationType at = Granados.AuthenticationType.Password;
            f.AuthenticationType = at;

            if (at == Granados.AuthenticationType.KeyboardInteractive)
            {
                //Creating a new SSH connection over the underlying socket
                _conn        = Granados.SSHConnection.Connect(f, reader, s);
                reader._conn = _conn;
                Debug.Assert(_conn.AuthenticationResult == Granados.AuthenticationResult.Prompt);
                Granados.AuthenticationResult r = ((SSH2Connection)_conn).DoKeyboardInteractiveAuth(new string[] { password });
                Debug.Assert(r == Granados.AuthenticationResult.Success);
            }
            else
            {
                //NOTE: if you use public-key authentication, follow this sample instead of the line above:
                //f.AuthenticationType = AuthenticationType.PublicKey;
                f.IdentityFile = AppDomain.CurrentDomain.BaseDirectory + "Key-File.key";
                f.Password     = password;
                f.KeyCheck     = delegate(Granados.SSHConnectionInfo info)
                {
                    byte[] h = info.HostKeyMD5FingerPrint();
                    foreach (byte b in h)
                    {
                        Debug.Write(String.Format("{0:x2} ", b));
                    }
                    return(true);
                };

                //Creating a new SSH connection over the underlying socket
                _conn            = Granados.SSHConnection.Connect(f, reader, s);
                reader._conn     = _conn;
                ConnectionStatus = 1;   //TerminalSSH.ConnectionStatus = 1;
            }

            //Opening a shell
            Granados.SSHChannel ch = _conn.OpenShell(reader);
            reader._pf = ch;

            //you can get the detailed connection information in this way:
            //Granados.SSHConnectionInfo ci = _conn.ConnectionInfo;

            //Go to sample shell
            //SampleShell(reader);

            return(true);
        }
 /// <summary>
 /// Test cursor movements
 /// </summary>
 /// <param name="vs">Virtual screen</param>
 public static void WriteBigX(VirtualScreen vs)
 {
     vs.CleanScreen();
     for (int i=0; i<vs.Height; i++)
     {
         vs.Write('X'); // already moves cursor about one
         vs.MoveCursor(vs.Width); // test overflow
     }
     vs.Write('\r'); // beginning of last line
     for (int i=0; i<vs.Height; i++)
     {
         vs.Write('X'); // already moves cursor about one
         vs.MoveCursor(-vs.Width); // test overflow
     }
 }
 /// <summary>
 /// Write a byte block and strings
 /// </summary>
 /// <param name="vs">Virtual screen</param>
 public static void WriteBlockOperation(VirtualScreen vs)
 {
     vs.CleanScreen();
     byte[] tb = Encoding.ASCII.GetBytes("This is a test output");
     vs.WriteLine("New screen with test output:");
     for (int i=0; i<10; i++)
     {
         vs.WriteByte(tb);
     }
     vs.WriteLine("\n");
     for (int i=0; i<10; i++)
     {
         vs.WriteLine("Line output");
     }
 }