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

📄 conn.cs

📁 一个远程终端软件的源码
💻 CS
📖 第 1 页 / 共 2 页
字号:

    internal void Run(ViewOpts viewOpts)
    {
      this.viewOpts = viewOpts;
      Run();
    }

    internal void Run(ConnOpts opts)
    {
      this.opts = opts;
      Run();
    }

    internal void Run()
    {
      try
      {
        // Get connection details from the user.
        if(opts == null)
          GetConnDetails();

        // Establish a network (not VNC) connection with the connection manager.
        EstNetworkConn();

        // Make a connection to the server.
        if(opts.ConnMode == ConnMode.Active)
          Connect();
        else
          Listen();

        // Negotiate the protocol version with the server.
        NegoProtoVer();

        // Authenticate the user.
        Auth();

        // Send client initialization message.
        SendCliInit();

        // Read server initialization message.
        ReadServInit();

        SetPixelFormat();

        SetEncodings();

        // Create a display locally.
        CreateDisp();

        // Logically speaking I should send this AFTER sending a refresh request with the
        // default width and height. But for some strange reason it does not work on the
        // emulator (real devices work fine). I have to send this before the first refresh
        // request.
        // In addition, a refresh request must be sent here. If we wait until a resize frame
        // buffer message, we will wait forever.
        if(opts.ViewOpts.ServScaling != ServScaling.Default)
          SendSetScale((byte)opts.ViewOpts.ServScaling);

        // Ask the server to send us the entire screen.
        SendUpdReq(0, 0, frameBufWidth, frameBufHeight, false);

        termBgThread = false;
        (new Thread(new ThreadStart(Start))).Start();

        App.AddConn(this);
      }
      catch(IOException)
      {
        CleanUp();
        MessageBox.Show(App.GetStr("Unable to communicate with the server!"),
                        App.GetStr("Error"),
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Exclamation,
                        MessageBoxDefaultButton.Button1);
      }
      catch(QuietEx)
      {
        CleanUp();
      }
      catch(WarnEx ex)
      {
        CleanUp();
        MessageBox.Show(ex.Message,
                        App.GetStr("Error"),
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Exclamation,
                        MessageBoxDefaultButton.Button1);
      }
    }

    private void SendUpdReq(UInt16 x, UInt16 y, UInt16 width, UInt16 height, bool incremental)
    {
      byte[] msg = RfbProtoUtil.GetFrameBufUpdReqMsg(x, y, width, height, incremental);
      WriteBytes(msg, RfbCliMsgType.FrameBufUpdReq);
    }

    internal void SendSetScale(byte scale)
    {
      byte[] msg = RfbProtoUtil.GetSetScaleMsg(scale);
      WriteBytes(msg, RfbCliMsgType.SetScale);
    }

    private Color GetColorFromData(byte[] data, UInt32 offset)
    {
      return GetColorFromPixel(RfbProtoUtil.GetPixelFromData(data, offset, bytesPp));
    }

    private Color GetColorFromPixel(UInt32 pixel)
    {
      int red = (int)((pixel >> redShift) & redMax) * 255 / redMax;
      int green = (int)((pixel >> greenShift) & greenMax) * 255 / greenMax;
      int blue = (int)((pixel >> blueShift) & blueMax) * 255 / blueMax;
      return Color.FromArgb(red, green, blue);
    }

    private void ReadRawRect(Rectangle rect)
    {
      byte[] rectBytes = ReadBytes(rect.Width * rect.Height * bytesPp);

      view.LockFrameBuf();

      try
      {
        // TODO: Anything faster?
        int curPos = 0;
        for(int i = 0; i < rect.Height; i++)
        {
          for(int j = 0; j < rect.Width; j++)
          {
            view[(UInt16)(rect.X + j), (UInt16)(rect.Y + i)] = GetColorFromData(rectBytes, (UInt32)curPos);
            curPos += bytesPp;
          }
        }
      }
      catch(OverflowException)
      {
        // Swallow this exception. For some strange reason UltraVNC sends X and Y > 65K.
      }
      catch(ArgumentException)
      {
        // Swallow this exception. For some strange reason UltraVNC sends invalid values.
      }

      view.UnlockFrameBuf();
    }

    private void ReadCopyRect(Rectangle rect)
    {
      byte[] rectBytes = ReadBytes(RfbSize.CopyRect);
      CopyRectMsg srcRect = new CopyRectMsg(rectBytes);

      view.LockFrameBuf();
      view.CopyRect(rect, srcRect.X, srcRect.Y);
      view.UnlockFrameBuf();
    }

    private void FillRreRect(Rectangle rect, Color bgColor, RreSubRectMsg[] subRects)
    {
      view.LockFrameBuf();

      view.FillRect(rect, bgColor);
      for(int i = 0; i < subRects.Length; i++)
      {
        Rectangle subRect = new Rectangle();
        subRect.X = rect.X + subRects[i].X;
        subRect.Y = rect.Y + subRects[i].Y;
        subRect.Width = subRects[i].Width;
        subRect.Height = subRects[i].Height;
        view.FillRect(subRect, GetColorFromPixel(subRects[i].Pixel));
      }

      view.UnlockFrameBuf();
    }

    private void ReadRreRectCore(Rectangle rect, bool isCompact)
    {
      UInt32 numSubRects = ReadUInt32();
      byte[] data = ReadBytes(bytesPp);
      Color bgColor = GetColorFromData(data, 0);

      int subRectSize = bytesPp;
      if(isCompact)
        subRectSize += RfbSize.CoRreSubRect;
      else
        subRectSize += RfbSize.RreSubRect;

      RreSubRectMsg[] subRects = new RreSubRectMsg[numSubRects];
      for(int i = 0; i < numSubRects; i++)
      {
        byte[] rectBytes = ReadBytes(subRectSize);
        subRects[i] = new RreSubRectMsg(rectBytes, bytesPp, isCompact);
      }

      FillRreRect(rect, bgColor, subRects);
    }

    private void ReadRreRect(Rectangle rect)
    {
      ReadRreRectCore(rect, false);
    }

    private void ReadCoRreRect(Rectangle rect)
    {
      ReadRreRectCore(rect, true);
    }

    private void ReadHexRect(Rectangle rect)
    {
      Color bgColor = App.Black;
      UInt32 fgPixel = 0;
      Rectangle tile = new Rectangle();

      for(tile.Y = rect.Y; tile.Y < rect.Bottom; tile.Y += 16)
      {
        for(tile.X = rect.X; tile.X < rect.Right; tile.X += 16)
        {
          tile.Width = 16;
          tile.Height = 16;
          tile.Width = Math.Min(tile.Right, rect.Right) - tile.Left;
          tile.Height = Math.Min(tile.Bottom, rect.Bottom) - tile.Top;

          RfbHexSubEncoding encoding = (RfbHexSubEncoding)ReadByte();

          if((encoding & RfbHexSubEncoding.Raw) != 0)
          {
            ReadRawRect(tile);
            if(opts.ViewOpts.ScrnUpdAlgo == ScrnUpdAlgo.Asap)
              view.InvalidateRect(tile);
            continue;
          }

          byte[] data;
          if((encoding & RfbHexSubEncoding.BgSpec) != 0)
          {
            data = ReadBytes(bytesPp);
            bgColor = GetColorFromData(data, 0);
          }

          if((encoding & RfbHexSubEncoding.FgSpec) != 0)
          {
            data = ReadBytes(bytesPp);
            fgPixel = RfbProtoUtil.GetPixelFromData(data, 0, bytesPp);
          }

          byte numSubRects = 0;
          if((encoding & RfbHexSubEncoding.AnySubRects) != 0)
            numSubRects = ReadByte();

          bool subRectsColored = ((encoding & RfbHexSubEncoding.SubRectsColored) != 0);

          int subRectSize = RfbSize.HexSubRect;
          subRectSize += subRectsColored? (int)bytesPp : 0;
          RreSubRectMsg[] subRects = new RreSubRectMsg[numSubRects];
          byte[] rectBytes = ReadBytes(subRectSize * numSubRects);
          for(int i = 0; i < numSubRects; i++)
            subRects[i] = new HexSubRectMsg(rectBytes, (UInt32)(i * subRectSize), bytesPp, subRectsColored, fgPixel);
          FillRreRect(tile, bgColor, subRects);
          if(opts.ViewOpts.ScrnUpdAlgo == ScrnUpdAlgo.Asap)
            view.InvalidateRect(tile);
        }
      }
    }

    internal void SendUpdReq(bool incremental)
    {
      if(IsFmtChgPending)
      {
        IsFmtChgPending = false;
        SetPixelFormat();
        SendUpdReq(0, 0, frameBufWidth, frameBufHeight, false);
      }
      else
        SendUpdReq(0, 0, frameBufWidth, frameBufHeight, incremental);
    }

    private void ReadScrnUpd()
    {
      byte[] msg = ReadBytes(RfbSize.FrameBufUpd - 1);
      UInt16 numRects = RfbProtoUtil.GetNumRectsFromFrameBufUpdMsg(msg);

      for(int i = 0; i < numRects; i++)
      {
        msg = ReadBytes(RfbSize.FrameBufUpdRectHdr);
        FrameBufUpdRectMsgHdr frameBufUpdRectHdr = new FrameBufUpdRectMsgHdr(msg);
        Rectangle rect = new Rectangle(frameBufUpdRectHdr.X, frameBufUpdRectHdr.Y, frameBufUpdRectHdr.Width, frameBufUpdRectHdr.Height);

        if(frameBufUpdRectHdr.Encoding == RfbEncoding.NewFBSize)
        {
          frameBufWidth = (UInt16)rect.Width;
          frameBufHeight = (UInt16)rect.Height;
          if(!termBgThread)
            view.NewFrameBuf(frameBufWidth, frameBufHeight);
          break;
        }

        switch(frameBufUpdRectHdr.Encoding)
        {
          case RfbEncoding.Raw:
            ReadRawRect(rect);
            if(opts.ViewOpts.ScrnUpdAlgo == ScrnUpdAlgo.Asap)
              view.InvalidateRect(rect);
            break;
          case RfbEncoding.CopyRect:
            ReadCopyRect(rect);
            if(opts.ViewOpts.ScrnUpdAlgo == ScrnUpdAlgo.Asap)
              view.InvalidateRect(rect);
            break;
          case RfbEncoding.Rre:
            ReadRreRect(rect);
            if(opts.ViewOpts.ScrnUpdAlgo == ScrnUpdAlgo.Asap)
              view.InvalidateRect(rect);
            break;
          case RfbEncoding.CoRre:
            ReadCoRreRect(rect);
            if(opts.ViewOpts.ScrnUpdAlgo == ScrnUpdAlgo.Asap)
              view.InvalidateRect(rect);
            break;
          case RfbEncoding.Hex:
            ReadHexRect(rect);
            break;
          default:
            throw new WarnEx(App.GetStr("Server is using unknown encoding!"));
        }
      }

      if(opts.ViewOpts.ScrnUpdAlgo != ScrnUpdAlgo.Asap)
        view.Invalidate();

      // Do this in the UI thread so we always send data in one thread.
      view.SendUpdReq();
    }

    private void ReadServCutTxt()
    {
      // .NET CF does not have built-in support for the clipboard.
      // We ignore this message at the moment.

      byte[] msg = ReadBytes(RfbSize.ServCutTxt - 1);
      UInt32 len = RfbProtoUtil.GetLenFromServCutTxtMsg(msg);
      string txt = ReadAsciiStr((int)len);
    }

    private void ReadResizeFrameBuf()
    {
      byte[] msg = ReadBytes(RfbSize.ResizeFrameBuf - 1);
      ResizeFrameBufMsg resizeFrameBufMsg = new ResizeFrameBufMsg(msg);
      frameBufWidth = resizeFrameBufMsg.Width;
      frameBufHeight = resizeFrameBufMsg.Height;
      // This call actually involves an Invoke, so we need to check termBgThread to make
      // sure that it does not hang.
      // TODO: Time to reorg the codebase...
      if(!termBgThread)
        view.ResizeFrameBuf(frameBufWidth, frameBufHeight);
    }

    /// <summary>
    ///   This is the entry point of the background thread that handles
    ///   server messages.
    /// </summary>
    private void Start()
    {
      // This is a background thread so the priority should be lower.
      Thread.CurrentThread.Priority = ThreadPriority.BelowNormal;

      try
      {
        while(!termBgThread)
        {
          // Yield to other threads so this thread does not dominate.
          Thread.Sleep(App.Delta);

          // Avoid the blocking ReadByte() if we have nothing to read.
          if(!stream.DataAvailable)
            continue;

          RfbServMsgType msgType = (RfbServMsgType)ReadByte();
          switch(msgType)
          {
            case RfbServMsgType.FrameBufUpd:
              ReadScrnUpd();
              break;
            case RfbServMsgType.SetColorMapEntries:
              throw new WarnEx(App.GetStr("The server is sending SetColorMapEntries!"));
            case RfbServMsgType.Bell:
              break;
            case RfbServMsgType.ServCutTxt:
              ReadServCutTxt();
              break;
            case RfbServMsgType.ResizeFrameBuf:
              ReadResizeFrameBuf();
              break;
            default:
              throw new WarnEx(App.GetStr("The server is sending unknown message!"));
          }
        }
      }
      catch(SocketException)
      {
        MessageBox.Show(App.GetStr("Unable to communicate with the server!"),
                        App.GetStr("Error"),
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Exclamation,
                        MessageBoxDefaultButton.Button1);
        // If termBgThread is true then view has been closed.
        // Don't Invoke or this thread will hang due to a .NET CF bug.
        // Technically speaking there is a slight chance that the view closes before Invoke
        // but after checking termBgThread, so this is not bullet proof.
        if(!termBgThread)
          view.Invoke(closeHdr);
      }
      catch(IOException)
      {
        MessageBox.Show(App.GetStr("Unable to communicate with the server!"),
                        App.GetStr("Error"),
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Exclamation,
                        MessageBoxDefaultButton.Button1);
        if(!termBgThread)
          view.Invoke(closeHdr);
      }
      catch(QuietEx)
      {
        if(!termBgThread)
          view.Invoke(closeHdr);
      }
      catch(WarnEx ex)
      {
        MessageBox.Show(ex.Message,
                        App.GetStr("Error"),
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Exclamation,
                        MessageBoxDefaultButton.Button1);
        if(!termBgThread)
          view.Invoke(closeHdr);
      }
      finally
      {
        CleanUp();
      }
    }
  }
}

⌨️ 快捷键说明

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