⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 conn.cs

📁 一个远程终端软件的源码
💻 CS
📖 第 1 页 / 共 2 页
字号:
//  Copyright (c) 2004-2005, 2007 Rocky Lo. All Rights Reserved.
//  Copyright (C) 2002 Ultr@VNC Team Members. All Rights Reserved.
//  Copyright (C) 2000-2002 Const Kaplinsky. All Rights Reserved.
//  Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
//  Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
//
//  This file is part of the VNC system.
//
//  The VNC system is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation; either version 2 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
//  USA.
//
// If the source code for the VNC system is not available from the place 
// whence you received this file, check http://www.uk.research.att.com/vnc or contact
// the authors on vnc@uk.research.att.com for information on obtaining it.

using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Drawing;
using System.Reflection;
using System.Windows.Forms;
using System.Collections;
using Vnc.RfbProto;
using Vnc.Security;
using SystemEx.WindowCE.Net;

namespace Vnc.Viewer
{
  /// <remarks>
  ///   This class represents a connection to the server.
  ///   It prompts a user for the connection details, connects to the server,
  ///   creates a display, and then handles server messages.
  /// </remarks>
  internal class Conn
  {
    /// <summary>
    ///   This is the version number we report to the server. At the moment we
    ///   "borrow" this from the UltraVNC viewer.
    /// </summary>
    // TODO: Have we implemented everything needed in order to say that we are
    // compliant to this version?
    private const byte ViewerRfbMajorVer = 3;
    private const byte ViewerRfbMinorVer = 4;

    // These are cleaned up upon termination because they contain initial
    // values of a connection object.
    private ConnOpts opts = null;
    private ViewOpts viewOpts = null;

    // These are cleaned up upon termination because they contain
    // unmanaged resources.
    private TcpClient tcpClient = null;
    private NetworkStream stream = null;
    private BinaryReader reader = null;
    private BinaryWriter writer = null;
    private NetworkConn networkConn = null;

    // These are set each time a connection is run.
    private ServInit servInit = null;
    private string desktopName = null;
    private int majorVer = -1;
    private int minorVer = -1;
    private View view = null;
    private bool termBgThread = false;
    private byte bytesPp = 0;
    private byte bpp = 0;
    private byte depth = 0;
    private bool isBigEndian = false;
    private bool isTrueColor = false;
    private UInt16 redMax = 0;
    private UInt16 greenMax = 0;
    private UInt16 blueMax = 0;
    private byte redShift = 0;
    private byte greenShift = 0;
    private byte blueShift = 0;
    private UInt16 frameBufWidth = 0;
    private UInt16 frameBufHeight = 0;
    internal bool IsFmtChgPending = false;

    private EventHandler closeHdr = null;

    internal Conn()
    {
      closeHdr = new EventHandler(CloseView);
    }

    private void CloseView(object sender, EventArgs e)
    {
      // Do this in the main thread.
      view.Close();
    }

    private void ViewClosed(object sender, EventArgs e)
    {
      termBgThread = true;
      App.RemoveConn(this);
    }

    private void GetConnDetails()
    {
      SessDlg sessDlg;
      if(viewOpts == null)
        sessDlg = SessDlgFactory.Create();
      else
        sessDlg = SessDlgFactory.Create(viewOpts);
      if(sessDlg.ShowDialog() != DialogResult.OK)
        throw new QuietEx();
      opts = sessDlg.ConnOpts;
    }

    private void Connect()
    {
      try
      {
        try
        {
          IPAddress ipAdr = IPAddress.Parse(opts.Host);
          IPEndPoint ipEndPt = new IPEndPoint(ipAdr, opts.Port);
          tcpClient = new TcpClient();
          tcpClient.Connect(ipEndPt);
        }
        catch(FormatException)
        {
          tcpClient = new TcpClient(opts.Host, opts.Port);
        }
        stream = tcpClient.GetStream();
        reader = new BinaryReader(stream, Encoding.ASCII);
        writer = new BinaryWriter(stream, Encoding.ASCII);
      }
      catch(SocketException)
      {
        throw new WarnEx(App.GetStr("Unable to connect to the specified server!"));
      }
    }

    private void Listen()
    {
      TcpListener listener = new TcpListener(IPAddress.Any, opts.Port);
      try
      {
        listener.Start();

        ListenDlg listenDlg = new ListenDlg(listener);
        if(listenDlg.ShowDialog() != DialogResult.OK)
          throw new QuietEx();

        tcpClient = listener.AcceptTcpClient();
        stream = tcpClient.GetStream();
        reader = new BinaryReader(stream, Encoding.ASCII);
        writer = new BinaryWriter(stream, Encoding.ASCII);
      }
      catch(SocketException)
      {
        throw new WarnEx(App.GetStr("Unable to get an incoming connection from the server!"));
      }
      finally
      {
        try
        {
          listener.Stop();
        }
        catch
        {}
      }
    }

    private string ReadAsciiStr(int numChars)
    {
      if(numChars == 0)
        return String.Empty;

      char[] chars = reader.ReadChars(numChars);
      return new string(chars);
    }

    private byte ReadByte()
    {
      return reader.ReadByte();
    }

    private byte[] ReadBytes(int numBytes)
    {
      if(numBytes == 0)
        return new byte[0];

      return reader.ReadBytes(numBytes);
    }

    private UInt32 ReadUInt32()
    {
      Int32 result = reader.ReadInt32();
      result = IPAddress.NetworkToHostOrder(result);
      return unchecked((UInt32)result);
    }

    private void WriteAsciiStr(string str)
    {
      writer.Write(str.ToCharArray());
    }

    private void WriteBytes(byte[] bytes)
    {
      writer.Write(bytes);
    }

    internal void WriteBytes(byte[] bytes, RfbCliMsgType msgType)
    {
      WriteBytes(bytes);
    }

    private void NegoProtoVer()
    {
      string verMsg = ReadAsciiStr(RfbSize.VerMsg);
      if(!RfbProtoUtil.IsValidVerMsg(verMsg))
        throw new WarnEx(App.GetStr("The server is not a VNC server!"));

      RfbProtoUtil.GetVerFromMsg(verMsg, out majorVer, out minorVer);

      if(majorVer == 3 && minorVer < 3)
        throw new WarnEx(App.GetStr("This server version is not supported!"));
      else
      {
        majorVer = ViewerRfbMajorVer;
        minorVer = ViewerRfbMinorVer;
      }

      verMsg = RfbProtoUtil.GetVerMsg(majorVer, minorVer);
      WriteAsciiStr(verMsg);
    }

    private void CreateDisp()
    {
      view = ViewFactory.Create(this, opts, frameBufWidth, frameBufHeight);
      view.Text = desktopName;
      view.Closed += new EventHandler(ViewClosed);
      view.Show();
    }

    private void Auth()
    {
      RfbAuthScheme authScheme = (RfbAuthScheme)ReadUInt32();
      switch(authScheme)
      {
        case RfbAuthScheme.ConnFailed:
          throw new WarnEx(App.GetStr("Connection failed at authentication!"));
        case RfbAuthScheme.NoAuth:
          break;
        case RfbAuthScheme.VncAuth:

          if(opts.Passwd == null || opts.Passwd.Length == 0)
          {
            AuthDlg authDlg = new AuthDlg();
            if(authDlg.ShowDialog() != DialogResult.OK)
              throw new QuietEx();

            if(authDlg.Passwd.Length <= 0)
              throw new WarnEx(App.GetStr("Empty password!"));
            opts.Passwd = authDlg.Passwd;
          }

          byte[] challenge = ReadBytes(RfbSize.AuthChallenge);

          VncAuth.EncryptBytes(challenge, opts.Passwd);
          WriteBytes(challenge);

          RfbAuthResult authResult = (RfbAuthResult)ReadUInt32();
          switch(authResult)
          {
            case RfbAuthResult.Ok:
              break;
            case RfbAuthResult.Failed:
              throw new WarnEx(App.GetStr("Authentication failed!"));
            case RfbAuthResult.TooMany:
              throw new WarnEx(App.GetStr("Too many!"));
            default:
              throw new WarnEx(App.GetStr("Authentication failed but reason unknown!"));
          }

          break;
        default:
          throw new WarnEx(App.GetStr("Authentication scheme unknown!"));
      }
    }

    private void SendCliInit()
    {
      byte[] msg = RfbProtoUtil.GetCliInitMsg(opts.ViewOpts.ShareServ);
      WriteBytes(msg);
    }

    private void ReadServInit()
    {
      byte[] msg = ReadBytes(RfbSize.ServInit);
      servInit = new ServInit(msg);
      frameBufWidth = servInit.Width;
      frameBufHeight = servInit.Height;
      desktopName = ReadAsciiStr((int)servInit.NameLen);
    }

    private void SetPixelFormat()
    {
      byte[] msg;
      if(opts.ViewOpts.PixelSize == PixelSize.Force8Bit)
      {
        bpp = 8;
        depth = 8;
        isBigEndian = false;
        isTrueColor = true;
        redMax = 7;
        greenMax = 7;
        blueMax = 3;
        redShift = 0;
        greenShift = 3;
        blueShift = 6;
        bytesPp = 1;
      }
      else if(opts.ViewOpts.PixelSize == PixelSize.Force16Bit || !servInit.IsTrueColor)
      {
        bpp = 16;
        depth = 16;
        isBigEndian = false;
        isTrueColor = true;
        redMax = 63;
        greenMax = 31;
        blueMax = 31;
        redShift = 0;
        greenShift = 6;
        blueShift = 11;
        bytesPp = 2;
      }
      else
      {
        bpp = servInit.Bpp;
        depth = servInit.Depth;
        isBigEndian = false;
        isTrueColor = servInit.IsTrueColor;
        redMax = servInit.RedMax;
        greenMax = servInit.GreenMax;
        blueMax = servInit.BlueMax;
        redShift = servInit.RedShift;
        greenShift = servInit.GreenShift;
        blueShift = servInit.BlueShift;
        bytesPp = (byte)((bpp + 7) / 8);
      }
      msg = RfbProtoUtil.GetSetPixelFormatMsg(bpp, depth, isBigEndian, isTrueColor, redMax, greenMax, blueMax, redShift, greenShift, blueShift);
      WriteBytes(msg, RfbCliMsgType.SetPixelFormat);
    }

    private void SetEncodings()
    {
      // We use a stack here.  The least favored encoding is pushed onto the stack first.
      Stack stack = new Stack();
      stack.Push(RfbEncoding.Raw);
      stack.Push(RfbEncoding.CopyRect);
      stack.Push(RfbEncoding.Rre);

      // We do support CoRRE encoding.
      // However, Ultra-VNC server is broken.
      // If we use CoRRE and server-side scaling is enabled, the server will
      // send us frame buffer updates with number of rectangles set incorrectly.
      // So the morale of the story is not to use CoRRE. If we know the server
      // does not scale the buffer, then we can enable CoRRE.
      // But this can all be avoided by using Hextile.
      //stack.Push(RfbEncoding.CoRre);

      stack.Push(RfbEncoding.Hex);

      stack.Push(RfbEncoding.NewFBSize);

      byte[] msg;
      msg = RfbProtoUtil.GetSetEncodingsMsgHdr((UInt16)stack.Count);
      WriteBytes(msg, RfbCliMsgType.SetEncodings);
      RfbEncoding[] encodings = new RfbEncoding[stack.Count];
      stack.ToArray().CopyTo(encodings, 0);
      msg = RfbProtoUtil.GetSetEncodingsMsg(encodings);
      WriteBytes(msg);
    }

    private void EstNetworkConn()
    {
      // We use the connection manager on PPCs and Smartphones.
      if(App.DevCap.Lvl >= DevCapLvl.Desktop)
        return;

      networkConn = new NetworkConn("http://" + opts.Host + "/");
      networkConn.Est();
    }

    private void RelNetworkConn()
    {
      // We use the connection manager on PPCs and Smartphones.
      if(App.DevCap.Lvl >= DevCapLvl.Desktop)
        return;

      if(networkConn != null)
      {
        networkConn.Rel();
        networkConn = null;
      }
    }

    private void CleanUp()
    {
      // We don't cleanup majorVer, minorVer, etc. here because
      // we will always read them when run is called.
      if(writer != null)
      {
        writer.Close();
        writer = null;
      }
      if(reader != null)
      {
        reader.Close();
        reader = null;
      }
      if(stream != null)
      {
        stream.Close();
        stream = null;
      }
      if(tcpClient != null)
      {
        tcpClient.Close();
        tcpClient = null;
      }
      RelNetworkConn();
      opts = null;
      viewOpts = null;
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -