예제 #1
0
 public void Setup(TelnetSingletonServer tServer)
 {
     telnetServer = tServer;
     lastMenuQueryTime = DateTime.MinValue; // Force a stale timestamp the first time.
     telnetServer.Write( (char)UnicodeCommand.TITLEBEGIN + "kOS Terminal Server Welcome Menu" + (char)UnicodeCommand.TITLEEND );
     forceMenuReprint = true; // force it to print the menu once the first time regardless of the state of the CPU list.
 }
예제 #2
0
파일: TermWindow.cs 프로젝트: KSP-KOS/KOS
 /// <summary>
 /// Tell the telnet session to resize itself
 /// </summary>
 /// <param name="telnet">which telnet session to send to</param>
 /// <param name="width">new width</param>
 /// <param name="height">new height</param>
 /// <param name="unconditional">if true, then send the resize message no matter what.  If false,
 /// then only send it if we calculate that the size changed.</param>
 private void ResizeAndRepaintTelnet(TelnetSingletonServer telnet, int width, int height, bool unconditional)
 {
     // Don't bother telling it to resize if its already the same size - this should stop resize spew looping:
     if (unconditional || telnet.ClientWidth != width || telnet.ClientHeight != height)
     {
         string resizeCmd = new string( new [] {(char)UnicodeCommand.RESIZESCREEN, (char)width, (char)height} );
         telnet.Write(resizeCmd);
         RepaintTelnet(telnet, true);
     }
 }
예제 #3
0
파일: TermWindow.cs 프로젝트: KSP-KOS/KOS
        /// <summary>
        /// Cover the case where the whole screen needs to be repainted from scratch.
        /// </summary>
        /// <param name="telnet">which telnet to paint to.</param>
        private void RepaintTelnetFull(TelnetSingletonServer telnet)
        {
            List<IScreenBufferLine> buffer = mostRecentScreen.Buffer; // just to keep the name shorter below:

            // Sometimes the buffer is shorter than the terminal height if the resize JUST happened in the last Update():
            int rowsToPaint = Math.Min(shared.Screen.RowCount, buffer.Count);

            telnet.Write((char)UnicodeCommand.CLEARSCREEN);
            for (int row = 0 ; row < rowsToPaint ; ++row)
            {
                IScreenBufferLine lineBuffer = buffer[row];
                int columnOfLastContent = -1;
                for (int col = 0 ; col < lineBuffer.Length ; ++col)
                {
                    char ch = lineBuffer[col];
                    switch (ch)
                    {
                        case (char)0x0000: // The buffer pads null chars into the 'dead' space of the screen past the last printed char.
                            break;
                        case (char)0x0009: // tab chars - really shouldn't be in the buffer.
                            break;
                        default:
                            columnOfLastContent = col;
                            break;
                    }
                }
                if (columnOfLastContent >= 0) // skip for empty lines
                {
                    string line = lineBuffer.ToString().Substring(0, columnOfLastContent+1);
                    telnet.Write(line);
                }
                if (row < rowsToPaint-1) //don't write the eoln for the lastmost line.
                    telnet.Write((char)UnicodeCommand.STARTNEXTLINE);
            }

            // ensure cursor locatiom (in case it's not at the bottom):
            telnet.Write(String.Format("{0}{1}{2}",
                                       (char)UnicodeCommand.TELEPORTCURSOR,
                                       // The next two are cast to char because, for example, a value of 76 should be
                                       // encoded as (char)76 (which is 'L'), rather than as '7' followed by '6':
                                       (char)mostRecentScreen.CursorColumn,
                                       (char)mostRecentScreen.CursorRow));

            prevTelnetScreens[telnet] = mostRecentScreen.DeepCopy();
        }
예제 #4
0
파일: TermWindow.cs 프로젝트: KSP-KOS/KOS
 internal void SendTitleToTelnet(TelnetSingletonServer telnet)
 {
     // Make the telnet client learn about the new title:
     string changeTitleCmd = String.Format("{0}{1}{2}",
                                           (char)UnicodeCommand.TITLEBEGIN,
                                           TitleText,
                                           (char)UnicodeCommand.TITLEEND);
     telnet.Write(changeTitleCmd);
 }
예제 #5
0
파일: TermWindow.cs 프로젝트: KSP-KOS/KOS
        /// <summary>
        /// Do the repaint of the telnet session.
        /// </summary>
        /// <param name="telnet">which telnet session to repaint</param>
        /// <param name="fullSync">if true, then ignore the diffing algorithm and just redraw everything.</param>
        internal void RepaintTelnet(TelnetSingletonServer telnet, bool fullSync)
        {
            if (fullSync || prevTelnetScreens[telnet] == null)
            {
                RepaintTelnetFull(telnet);
                return;
            }

            // If the state of the screen reverse, or the visual bell flags, has changed since last time,
            // spit out the characters to change the state:
            if (telnet.ReverseScreen != shared.Screen.ReverseScreen)
            {
                telnet.Write(shared.Screen.ReverseScreen ? ((char)UnicodeCommand.REVERSESCREENMODE) : ((char)UnicodeCommand.NORMALSCREENMODE));
                telnet.ReverseScreen = shared.Screen.ReverseScreen;
            }
            if (telnet.VisualBeep != shared.Screen.VisualBeep)
            {
                telnet.Write(shared.Screen.VisualBeep ? ((char)UnicodeCommand.VISUALBEEPMODE) : ((char)UnicodeCommand.AUDIOBEEPMODE));
                telnet.VisualBeep = shared.Screen.VisualBeep;
            }
            string updateText = mostRecentScreen.DiffFrom(prevTelnetScreens[telnet]);
            telnet.Write(updateText);

            prevTelnetScreens[telnet] = mostRecentScreen.DeepCopy();
            for (int i = 0 ; i < shared.Screen.BeepsPending ; ++i)
                telnet.Write((char)UnicodeCommand.BEEP); // The terminal's UnicodeMapper will convert this to ascii 0x07 if the right terminal type.
        }
예제 #6
0
파일: TermWindow.cs 프로젝트: KSP-KOS/KOS
 internal void DetachTelnet(TelnetSingletonServer server)
 {
     server.DisconnectFromProcessor();
     telnets.Remove(server);
 }
예제 #7
0
파일: TermWindow.cs 프로젝트: KSP-KOS/KOS
 internal void AttachTelnet(TelnetSingletonServer server)
 {
     telnets.AddUnique(server);
     prevTelnetScreens[server] = null;
 }
예제 #8
0
파일: TermWindow.cs 프로젝트: KSP-KOS/KOS
        /// <summary>
        /// Respond to one single input character in Unicode, using the pretend
        /// virtual Unicode terminal keycodes described in the UnicodeCommand enum.
        /// To keep things simple, all key input is coerced into single Unicode chars
        /// even if the actual keypress takes multiple characters to express in its
        /// native form (i.e. ESC [ A means left-arrow on a VT100 terminal.  If
        /// a telnet is talking via VT100 codes, that ESC [ A will get converted into
        /// a single UnicdeCommand.LEFTCURSORONE character before being sent here.)
        /// <br/>
        /// This method is public because it is also how other mods should send input
        /// to the terminal if they want some other source to send simulated keystrokes.
        /// </summary>
        /// <param name="ch">The character, which might be a UnicodeCommand char</param>
        /// <param name="whichTelnet">If this came from a telnet session, which one did it come from?
        /// Set to null in order to say it wasn't from a telnet but was from the interactive GUI</param>
        /// <param name="doQueuing">true if the keypress should get queued if we're not ready for it
        /// right now.  If false, then the keypress will be ignored if we're not ready for it.</param>
        public void ProcessOneInputChar(char ch, TelnetSingletonServer whichTelnet, bool doQueuing = true)
        {
            // Weird exceptions for multi-char data combos that would have been begun on previous calls to this method:
            switch (inputExpected)
            {
                case ExpectNextChar.RESIZEWIDTH:
                    pendingWidth = ch;
                    inputExpected = ExpectNextChar.RESIZEHEIGHT;
                    return;
                case ExpectNextChar.RESIZEHEIGHT:
                    int height = ch;
                    shared.Screen.SetSize(height, pendingWidth);
                    inputExpected = ExpectNextChar.NORMAL;
                    return;
                default:
                    break;
            }

            // Printable ASCII section of Unicode - the common vanilla situation
            // (Idea: Since this is all Unicode anyway, should we allow a wider range to
            // include multi-language accent characters and so on?  Answer: to do so we'd
            // first need to expand the font pictures in the font image file, so it's a
            // bigger task than it may first seem.)
            if (0x0020 <= ch && ch <= 0x007f)
            {
                 Type(ch, doQueuing);
            }
            else
            {
                switch(ch)
                {
                    // A few conversions from UnicodeCommand into those parts of ASCII that it
                    // maps directly into nicely, otherwise just pass it through to SpecialKey():

                    case (char)UnicodeCommand.DELETELEFT:
                    case (char)8:
                        Type((char)8, doQueuing);
                        break;
                    case (char)UnicodeCommand.STARTNEXTLINE:
                    case '\r':
                        Type('\r', doQueuing);
                        break;
                    case '\t':
                        Type('\t', doQueuing);
                        break;
                    case (char)UnicodeCommand.RESIZESCREEN:
                        inputExpected = ExpectNextChar.RESIZEWIDTH;
                        break; // next expected char is the width.

                    // Finish session:  If GUI, then close window.  If Telnet, then detatch from the session:

                    case (char)0x0004/*control-D*/: // How users of unix shells are used to doing this.
                    case (char)0x0018/*control-X*/: // How kOS did it in the past in the GUI window.
                        if (shared.Interpreter.IsAtStartOfCommand())
                        {
                            if (whichTelnet == null)
                                Close();
                            else
                                whichTelnet.DisconnectFromProcessor();
                        }
                        break;

                    // User asking for redraw (Unity already requires that we continually redraw the GUI Terminal, so this is only meaningful for telnet):

                    case (char)UnicodeCommand.REQUESTREPAINT:
                        if (whichTelnet != null)
                        {
                            ResizeAndRepaintTelnet(whichTelnet, shared.Screen.ColumnCount, shared.Screen.RowCount, true);
                        }
                        break;

                    // Typical case is to just let SpecialKey do the work:

                    default:
                        SpecialKey(ch, doQueuing);
                        break;
                }
            }

            // else ignore it - unimplemented char.
        }
예제 #9
0
 internal void SingletonStopped(TelnetSingletonServer telnet)
 {
     telnets.Remove(telnet);
 }
예제 #10
0
        public void Update()
        {
            SetConfigEnable(SafeHouse.Config.EnableTelnet);

            int howManySpawned = 0;

            if (!isListening)
            {
                // Doing the command:
                //     SET CONFIG:TELNET TO FALSE.
                // should kill any singleton telnet servers that may have been started in the past
                // when it was true.  This does that:
                foreach (TelnetSingletonServer singleServer in telnets)
                {
                    singleServer.StopListening();
                    telnets.Remove(singleServer);
                }

                // disabled, so don't listen for connections.
                return;
            }

            // .NET's TCP handler only gives you blocking socket accepting, but for the Unity
            // Update(), we need to always finish quickly and never block, so check if anything
            // is pending first to simulate the effect of a nonblocking socket accept check:
            if (!server.Pending())
                return;

            TcpClient incomingClient = server.AcceptTcpClient();

            string remoteIdent = ((IPEndPoint)(incomingClient.Client.RemoteEndPoint)).Address.ToString();
            SafeHouse.Logger.Log(string.Format("{0} telnet server got an incoming connection from {1}", KSPLogger.LOGGER_PREFIX, remoteIdent));

            TelnetSingletonServer newServer = new TelnetSingletonServer(this, incomingClient, ++howManySpawned);
            telnets.Add(newServer);
            newServer.StartListening();
        }
예제 #11
0
 public void Detach()
 {
     enabled = false;
     telnetServer = null;
 }