Exemple #1
0
        /// <summary>
        /// Creates the encoded pixel data in a form of an EncodedRectangle with the preferred encoding.
        /// </summary>
        private void DoFrameBufferUpdate(Framebuffer fb, bool incremental, int x, int y, int width, int height)
        {
            //if (incremental)
            //    return;
            Trace.WriteLine("X: " + x + " Y: " + y + " W: " + fb.Width + " H: " + fb.Height);
            int w = fb.Width;
            int h = fb.Height;

            if ((x < 0) || (y < 0) || (width <= 0) || (height <= 0))
            {
                Trace.WriteLine("Neg:" + x + ":" + y + ":" + width + ":" + height);
                return;
            }
            if (x + width > w)
            {
                Trace.WriteLine("Too wide");
                return;
            }
            if (y + height > h)
            {
                Trace.WriteLine("Too high");
                return;
            }
            Trace.WriteLine("Bounds OK!");

            HashSet <EncodedRectangle> rectangles = new HashSet <EncodedRectangle>();

            try
            {
                Stopwatch tip = Stopwatch.StartNew();
                EncodedRectangleFactory factory = new EncodedRectangleFactory(this, fb);

                ICollection <QuadNode> list = screenHandler.GetChange();

                Trace.WriteLine(list.Count + " rectangles to encode");
                foreach (QuadNode iter in list)
                {
                    Trace.WriteLine(iter.ToString());
                    EncodedRectangle localRect = factory.Build(iter, GetPreferredEncoding());
                    localRect.Encode();

                    rectangles.Add(localRect);
                }
                Trace.WriteLine("Encoding took: " + tip.Elapsed);
            }
            catch (Exception localException)
            {
                Console.WriteLine(localException.StackTrace);
                if (localException is IOException)
                {
                    Close(); return;
                }
            }
            if (rectangles.Count != 0)
            {
                WriteFrameBufferUpdate(rectangles);
            }
        }
        /// <summary>
        /// Creates an object type derived from EncodedRectangle, based on the value of encoding.
        /// </summary>
        /// <param name="rectangle">A Rectangle object defining the bounds of the rectangle to be created</param>
        /// <param name="encoding">An Integer indicating the encoding type to be used for this rectangle.  Used to determine the type of EncodedRectangle to create.</param>
        /// <returns></returns>
        public EncodedRectangle Build(Rectangle rectangle, int encoding)
        {
            EncodedRectangle e = null;

            switch (encoding)
            {
            case RfbProtocol.RAW_ENCODING:
                e = new RawRectangle(rfb, framebuffer, rectangle);
                break;

            case RfbProtocol.COPYRECT_ENCODING:
                e = new CopyRectRectangle(rfb, framebuffer, rectangle);
                break;

            case RfbProtocol.RRE_ENCODING:
                e = new RreRectangle(rfb, framebuffer, rectangle);
                break;

            case RfbProtocol.CORRE_ENCODING:
                e = new CoRreRectangle(rfb, framebuffer, rectangle);
                break;

            case RfbProtocol.HEXTILE_ENCODING:
                e = new HextileRectangle(rfb, framebuffer, rectangle);
                break;

            case RfbProtocol.ZRLE_ENCODING:
                e = new ZrleRectangle(rfb, framebuffer, rectangle);
                break;

            case RfbProtocol.CURSOR_PSEUDO_ENCODING:
                e = new CursorRectangle(rfb, framebuffer, rectangle);
                break;

            default:
                // Sanity check
                throw new Exception("Unsupported Encoding Format received: " + encoding.ToString() + ".");
            }
            return(e);
        }
        /// <summary>
        /// Creates an object type derived from EncodedRectangle, based on the value of encoding.
        /// </summary>
        /// <param name="rectangle">A Rectangle object defining the bounds of the rectangle to be created</param>
        /// <param name="encoding">An Integer indicating the encoding type to be used for this rectangle.  Used to determine the type of EncodedRectangle to create.</param>
        /// <returns></returns>
        public EncodedRectangle Build(Rectangle rectangle, int encoding)
        {
            EncodedRectangle e = null;

            switch (encoding)
            {
            case RfbProtocol.RAW_ENCODING:
                e = new RawRectangle(rfb, framebuffer, rectangle);
                break;

            case RfbProtocol.COPYRECT_ENCODING:
                e = new CopyRectRectangle(rfb, framebuffer, rectangle);
                break;

            case RfbProtocol.RRE_ENCODING:
                e = new RreRectangle(rfb, framebuffer, rectangle);
                break;

            case RfbProtocol.CORRE_ENCODING:
                e = new CoRreRectangle(rfb, framebuffer, rectangle);
                break;

            case RfbProtocol.HEXTILE_ENCODING:
                e = new HextileRectangle(rfb, framebuffer, rectangle);
                break;

            case RfbProtocol.ZRLE_ENCODING:
// TODO: ZRLE is not written yet, but when it is, this needs to be changed.
//					e = new ZrleRectangle(rfb, framebuffer, rectangle);
//					break;
                throw new NotImplementedException("Need to implement Zrle Encoding!!!");

            default:
                // Sanity check
                throw new VncProtocolException("Unsupported Encoding Format received: " + encoding.ToString() + ".");
            }
            return(e);
        }
        /// <summary>
        /// Worker thread lives here and processes protocol messages infinitely, triggering events or other actions as necessary.
        /// </summary>
        private void GetRfbUpdates()
        {
            int rectangles;
            int enc;

            // Get the initial destkop from the host
            RequestScreenUpdate(true);

            while (true)
            {
                if (CheckIfThreadDone())
                {
                    break;
                }

                try {
                    switch (rfb.ReadServerMessageType())
                    {
                    case RfbProtocol.FRAMEBUFFER_UPDATE:
                        rectangles = rfb.ReadFramebufferUpdate();

                        if (CheckIfThreadDone())
                        {
                            break;
                        }

                        for (int i = 0; i < rectangles; ++i)
                        {
                            // Get the update rectangle's info
                            Rectangle rectangle;
                            rfb.ReadFramebufferUpdateRectHeader(out rectangle, out enc);

                            // Build a derived EncodedRectangle type and pull-down all the pixel info
                            EncodedRectangle er = factory.Build(rectangle, enc);
                            er.Decode();

                            // Let the UI know that an updated rectangle is available, but check
                            // to see if the user closed things down first.
                            if (!CheckIfThreadDone() && VncUpdate != null)
                            {
                                VncEventArgs e = new VncEventArgs(er);

                                // In order to play nicely with WinForms controls, we do a check here to
                                // see if it is necessary to synchronize this event with the UI thread.
                                if (VncUpdate.Target is System.Windows.Forms.Control)
                                {
                                    Control target = VncUpdate.Target as Control;

                                    if (target != null)
                                    {
                                        target.Invoke(VncUpdate, new object[] { this, e });
                                    }
                                }
                                else
                                {
                                    // Target is not a WinForms control, so do it on this thread...
                                    VncUpdate(this, new VncEventArgs(er));
                                }
                            }
                        }
                        break;

                    case RfbProtocol.BELL:
                        Beep(500, 300);                                  // TODO: are there better values than these?
                        break;

                    case RfbProtocol.SERVER_CUT_TEXT:
                        if (CheckIfThreadDone())
                        {
                            break;
                        }
                        Clipboard.SetDataObject(rfb.ReadServerCutText().Replace("\n", Environment.NewLine), true);
                        break;

                    case RfbProtocol.SET_COLOUR_MAP_ENTRIES:
                        // TODO: Needs to be implemented fully
                        //						rfb.ReadColourMapEntry();
                        break;
                    }
                } catch {
                    OnConnectionLost();
                }
            }
        }
Exemple #5
0
        /// <summary>
        /// Worker thread lives here and processes protocol messages infinitely, triggering events or other actions as necessary.
        /// </summary>
        private void GetRfbUpdates()
        {
            Thread.Sleep(1000);

            int rectangles;
            int enc;

            // Get the initial destkop from the host
            RequestScreenUpdate(true);

            while (true)
            {
                if (CheckIfThreadDone())
                {
                    break;
                }

                try
                {
                    switch (rfb.ReadServerMessageType())
                    {
                    case RfbProtocol.FRAMEBUFFER_UPDATE:
                        rectangles = rfb.ReadFramebufferUpdate();

                        if (CheckIfThreadDone())
                        {
                            break;
                        }

                        // TODO: consider gathering all update rectangles in a batch and *then* posting the event back to the main thread.
                        for (int i = 0; i < rectangles; ++i)
                        {
                            // Get the update rectangle's info
                            Rectangle rectangle;
                            rfb.ReadFramebufferUpdateRectHeader(out rectangle, out enc);

                            // Build a derived EncodedRectangle type and pull-down all the pixel info
                            EncodedRectangle er = factory.Build(rectangle, BufferInfos.BitsPerPixel, enc);
                            er.Decode();

                            // Let the UI know that an updated rectangle is available, but check
                            // to see if the user closed things down first.
                            if (!CheckIfThreadDone())
                            {
                                updates.Add(er);
                            }
                        }
                        break;

                    case RfbProtocol.BELL:
                        Beep(500, 300);      // TODO: are there better values than these?
                        break;

                    case RfbProtocol.SERVER_CUT_TEXT:
                        if (CheckIfThreadDone())
                        {
                            break;
                        }
                        // TODO: This is invasive, should there be a bool property allowing this message to be ignored?
                        //           Clipboard.SetDataObject(rfb.ReadServerCutText().Replace("\n", Environment.NewLine), true);
                        OnServerCutText();
                        break;

                    case RfbProtocol.SET_COLOUR_MAP_ENTRIES:
                        rfb.ReadColourMapEntry();
                        break;
                    }
                }
                catch (Exception e)
                {
                    OnConnectionLost(e);
                }
            }
        }
Exemple #6
0
        /// <summary>
        /// Creates the encoded pixel data in a form of an EncodedRectangle with the preferred encoding.
        /// </summary>
        private void DoFrameBufferUpdate(Framebuffer fb, bool incremental, int x, int y, int width, int height)
        {
            //if (incremental)
            //    return;
            Trace.WriteLine("X: " + x + " Y: " + y + " W: " + fb.Width + " H: " + fb.Height);
            int w = fb.Width;
            int h = fb.Height;

            if ((x < 0) || (y < 0) || (width <= 0) || (height <= 0))
            {
                Trace.WriteLine("Neg:" + x + ":" + y + ":" + width + ":" + height);
                return;
            }
            if (x + width > w)
            {
                Trace.WriteLine("Too wide");
                return;
            }
            if (y + height > h)
            {
                Trace.WriteLine("Too high");
                return;
            }
            Trace.WriteLine("Bounds OK!");


            List <EncodedRectangle> lst = new List <EncodedRectangle>();

            //List<byte[]> lstHash = new List<byte[]>();
            try
            {
                //Console.WriteLine("Framebuffer: ");
                //fb.Print();
                //Console.ReadLine();

                System.Diagnostics.Stopwatch tip     = System.Diagnostics.Stopwatch.StartNew();
                EncodedRectangleFactory      factory = new EncodedRectangleFactory(this, fb);

                /*
                 * int i = width / 4;
                 * int j = height / 4;
                 * int m = 0;
                 * Rectangle lRect = Rectangle.Empty;
                 * for (int k = 0; k < 4; k++)
                 *  for (m = 0; m < 4; m++)
                 *  {
                 *      lRect = new Rectangle();
                 *      lRect.X = (i * k);
                 *      lRect.Y = (j * m);
                 *      lRect.Width = i;
                 *      lRect.Height = j;
                 *      //lRect = PixelGrabber.AlignRectangle(lRect, width, height);
                 *
                 *      EncodedRectangle localRect = factory.Build(lRect, GetPreferredEncoding());
                 *      localRect.Encode();
                 *      lst.Add(localRect);
                 *  }
                 */
                EncodedRectangle localRect = factory.Build(new Rectangle(x, y, width, height), GetPreferredEncoding());
                localRect.Encode();

                lst.Add(localRect);
                Console.WriteLine("Encoding took: " + tip.Elapsed);
            }
            catch (Exception localException)
            {
                Console.WriteLine(localException.StackTrace.ToString());
                if (localException is IOException)
                {
                    this.Close(); return;
                }
            }
            if (lst.Count != 0)
            {
                WriteFrameBufferUpdate(lst.ToArray());
            }
        }
        // vnc client handling - main thread
        private void RunNetThread()
        {
            while (!terminate)
            {
                if (autoconnect && host != "")
                {
                    try
                    {
                        sleeptime = 0;
                        Log.Info("Connecting to \"" + host + ":" + port + "\"...");
                        rfb = new RfbProtocol();
                        rfb.Connect(host, (int)port);
                        Log.Debug("Connected.");
                        rfb.ReadProtocolVersion();

                        // Handle possible repeater connection
                        if (rfb.ServerVersion == 0.0)
                        {
                            rfb.WriteProxyAddress();
                            // Now we are connected to the real server; read the protocol version of the
                            // server
                            rfb.ReadProtocolVersion();
                            // Resume normal handshake and protocol
                        }

                        rfb.WriteProtocolVersion();
                        Log.Debug("Protocol Version:" + rfb.ServerVersion);

                        // Figure out which type of authentication the server uses
                        byte[] types = rfb.ReadSecurityTypes();

                        // Based on what the server sends back in the way of supported Security Types, one of
                        // two things will need to be done: either the server will reject the connection (i.e., type = 0),
                        // or a list of supported types will be sent, of which we need to choose and use one.
                        if (types.Length > 0)
                        {
                            if (types[0] == 0)
                            {
                                // The server is not able (or willing) to accept the connection.
                                // A message follows indicating why the connection was dropped.
                                throw new Exception("Connection Failed. The server rejected the connection for the following reason: " + rfb.ReadSecurityFailureReason());
                            }
                            else
                            {
                                byte securityType = GetSupportedSecurityType(types);
                                if (securityType == 0)
                                {
                                    throw new Exception("Unknown Security Type(s), The server sent one or more unknown Security Types.");
                                }

                                rfb.WriteSecurityType(securityType);

                                // Protocol 3.8 states that a SecurityResult is still sent when using NONE (see 6.2.1)
                                if (rfb.ServerVersion >= 3.799f && rfb.ServerVersion <= 3.801 && securityType == 1)
                                {
                                    if (rfb.ReadSecurityResult() > 0)
                                    {
                                        // For some reason, the server is not accepting the connection.  Get the
                                        // reason and throw an exception
                                        throw new Exception("Unable to Connect to the Server. The Server rejected the connection for the following reason: " + rfb.ReadSecurityFailureReason());
                                    }
                                }

                                if (securityType > 1)
                                {
                                    byte[] challenge = rfb.ReadSecurityChallenge();
                                    rfb.WriteSecurityResponse(EncryptChallenge(pass, challenge));
                                    if (rfb.ReadSecurityResult() != 0)
                                    {
                                        // Authentication failed, and if the server is using Protocol version 3.8, a
                                        // plain text message follows indicating why the error happend.  I'm not
                                        // currently using this message, but it is read here to clean out the stream.
                                        // In earlier versions of the protocol, the server will just drop the connection.
                                        autoconnect = false;
                                        if (rfb.ServerVersion == 3.8)
                                        {
                                            throw new Exception("The server denyes the authentication. Reason: \"" + rfb.ReadSecurityFailureReason() + "\"");
                                        }
                                        throw new Exception("The server denyes the authentication.");
                                    }
                                }
                            }
                        }
                        else
                        {
                            // Something is wrong, since we should have gotten at least 1 Security Type
                            throw new Exception("Protocol Error Connecting to Server. The Server didn't send any Security Types during the initial handshake.");
                        }

                        // Finish initializing protocol with host
                        rfb.WriteClientInitialisation(shared);
                        buffer = rfb.ReadServerInit();
                        rfb.WriteSetPixelFormat(buffer);        // just use the server's framebuffer format

                        if (hideRemoteCursor)
                        {
                            rfb.WriteSetEncodings(new int[]
                            {
                                RfbProtocol.ZRLE_ENCODING,
                                RfbProtocol.HEXTILE_ENCODING,
                                RfbProtocol.RRE_ENCODING,
                                RfbProtocol.COPYRECT_ENCODING,
                                RfbProtocol.RAW_ENCODING,
                                RfbProtocol.CURSOR_PSEUDO_ENCODING
                            });
                        }
                        else
                        {
                            rfb.WriteSetEncodings(new int[]
                            {
                                RfbProtocol.ZRLE_ENCODING,
                                RfbProtocol.HEXTILE_ENCODING,
                                RfbProtocol.RRE_ENCODING,
                                RfbProtocol.COPYRECT_ENCODING,
                                RfbProtocol.RAW_ENCODING
                            });
                        }

                        // Create an EncodedRectangleFactory so that EncodedRectangles can be built according to set pixel layout
                        factory = new EncodedRectangleFactory(rfb, buffer);
                        // Get the initial destkop from the host

                        rfb.WriteFramebufferUpdateRequest(0, 0, (ushort)buffer.Width, (ushort)buffer.Height, false);

                        while (!terminate && autoconnect)
                        {
                            switch (rfb.ReadServerMessageType())
                            {
                            case RfbProtocol.FRAMEBUFFER_UPDATE:
                                int rectangles = rfb.ReadFramebufferUpdate();

                                for (int i = 0; i < rectangles; ++i)
                                {
                                    // Get the update rectangle's info
                                    Rectangle rectangle;
                                    int       enc;
                                    rfb.ReadFramebufferUpdateRectHeader(out rectangle, out enc);

                                    // Build a derived EncodedRectangle type and pull-down all the pixel info
                                    EncodedRectangle er = factory.Build(rectangle, enc);

                                    er.Decode();
                                    er.Draw();
                                }
                                break;

                            case RfbProtocol.BELL:
                                Log.Debug("Bell");
                                break;

                            case RfbProtocol.SERVER_CUT_TEXT:
                                rfb.ReadServerCutText();
                                Log.Debug("server-cut-text");
                                break;

                            case RfbProtocol.SET_COLOUR_MAP_ENTRIES:
                                Log.Debug("SET_COLOUR_MAP_ENTRIES");
                                rfb.ReadColourMapEntry();
                                break;

                            default:
                                throw new Exception("Unknown messagetype.");
                            }
                            invalid = true;
                            rfb.WriteFramebufferUpdateRequest(0, 0, (ushort)buffer.Width, (ushort)buffer.Height, true);
                        }
                    }
                    catch (SocketException)
                    {
                        Log.Info("Unable to connect to the server. Retry in 60s.");
                        sleeptime = 60000;
                    }
                    catch (IOException e)
                    {
                        Log.Debug("Exception in NetThread(" + e.GetType().ToString() + "): " + e.Message);
                    }
                    catch (Exception e)
                    {
                        Log.Error("Exception in NetThread(" + e.GetType().ToString() + "): " + e.Message);
                        sleeptime = 10000;
                    }
                    try
                    {
                        rfb.Close();
                    }
                    catch (Exception) {}
                    rfb     = null;
                    buffer  = null;
                    factory = null;
                    invalid = true;
                    Thread.Sleep(sleeptime);
                }
            }
        }
Exemple #8
0
        /// <summary>
        /// Worker thread lives here and processes protocol messages infinitely, triggering events or other actions as necessary.
        /// </summary>
        private void GetRfbUpdates(CancellationToken token)
        {
            // Get the initial destkop from the host
            int connLostCount = 0;

            RequestScreenUpdate(true);

            while (!token.IsCancellationRequested)
            {
                try
                {
                    // ReSharper disable once SwitchStatementMissingSomeCases
                    var msgType = rfb.ReadServerMessageType();
                    switch (msgType)
                    {
                    case ServerClientMessageType.FramebufferUpdate:
                        var rectangles = rfb.ReadFramebufferUpdate();

                        if (token.IsCancellationRequested)
                        {
                            break;
                        }

                        // TODO: consider gathering all update rectangles in a batch and *then* posting the event back to the main thread.
                        for (var i = 0; i < rectangles; ++i)
                        {
                            // Get the update rectangle's info
                            var(rectangle, enc) = rfb.ReadFramebufferUpdateRectHeader();

                            // Build a derived EncodedRectangle type and pull-down all the pixel info
                            var er = EncodedRectangle.Build(rfb, Framebuffer, rectangle, enc);
                            er.Decode();

                            // Let the UI know that an updated rectangle is available, but check
                            // to see if the user closed things down first.
                            if (token.IsCancellationRequested || VncUpdate == null)
                            {
                                continue;
                            }
                            var e = new VncEventArgs(er);

                            VncUpdate(this, new VncEventArgs(er));
                        }
                        break;

                    case ServerClientMessageType.Bell:
                        //Beep();
                        break;

                    case ServerClientMessageType.ServerCutText:

                        // TODO: This is invasive, should there be a bool property allowing this message to be ignored?
                        OnServerCutText();
                        break;

                    case ServerClientMessageType.SetColourMapEntries:
                        rfb.ReadColourMapEntry();
                        break;
                    }
                    // Moved screen update request here to prevent it being called multiple times
                    // This was the case when multiple rectangles were returned by the host
                    RequestScreenUpdate(FullScreenRefresh);
                    connLostCount = 0;
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.Message);
                    // On the first time of no data being received we force a complete update
                    // This is for times when the server has no update, and caused the timeout.
                    if (connLostCount++ > 1)
                    {
                        OnConnectionLost();
                    }
                    else
                    {
                        RequestScreenUpdate(true);
                    }
                }
                FullScreenRefresh = false;
            }
        }