public void NegotiateSecurityIncorrectPasswordTest()
        {
            using (var stream = new TestStream())
            {
                // Have the client send authentication method 'Password', which is what the server expects
                VncStream clientStream = new VncStream(stream.Input);
                clientStream.SendByte((byte)AuthenticationMethod.Password);
                clientStream.Send(new byte[16]); // An empty response
                stream.Input.Position = 0;

                var session = new VncServerSession();
                session.Connect(stream, null, startThread: false);

                Assert.False(session.NegotiateSecurity(new AuthenticationMethod[] { AuthenticationMethod.Password }));

                VncStream serverStream = new VncStream(stream.Output);
                stream.Output.Position = 0;

                // Server will have offered 1 authentication method, and failed to authenticate
                // the client
                Assert.Equal(1, serverStream.ReceiveByte());                                   // 1 authentication method offered
                Assert.Equal((byte)AuthenticationMethod.Password, serverStream.ReceiveByte()); // The authentication method offered
                Assert.NotEqual(0u, serverStream.ReceiveUInt32BE());                           // Challenge, part 1
                Assert.NotEqual(0u, serverStream.ReceiveUInt32BE());                           // Challenge, part 2
                Assert.NotEqual(0u, serverStream.ReceiveUInt32BE());                           // Challenge, part 3
                Assert.NotEqual(0u, serverStream.ReceiveUInt32BE());                           // Challenge, part 4
                Assert.Equal(1u, serverStream.ReceiveUInt32BE());                              // Authentication failed
                Assert.Equal("Failed to authenticate", serverStream.ReceiveString());          // Error message

                Assert.Equal(stream.Output.Length, stream.Output.Position);
                Assert.Equal(stream.Input.Length, stream.Input.Position);
            }
        }
        public void NegotiateSecurityInvalidMethodTest()
        {
            using (var stream = new TestStream())
            {
                // Have the client send authentication method 'None', while we only accept 'Password'
                VncStream clientStream = new VncStream(stream.Input);
                clientStream.SendByte((byte)AuthenticationMethod.None);
                stream.Input.Position = 0;

                var session = new VncServerSession();
                session.Connect(stream, null, startThread: false);

                Assert.False(session.NegotiateSecurity(new AuthenticationMethod[] { AuthenticationMethod.Password }));

                VncStream serverStream = new VncStream(stream.Output);
                stream.Output.Position = 0;

                // Server will have offered 1 authentication method, and disconnected when the client
                // accepted an invalid authentication method.
                Assert.Equal(1, serverStream.ReceiveByte());                                   // 1 authentication method offered
                Assert.Equal((byte)AuthenticationMethod.Password, serverStream.ReceiveByte()); // The authentication method offered
                Assert.Equal(1u, serverStream.ReceiveUInt32BE());                              // authentication failed
                Assert.Equal("Invalid authentication method.", serverStream.ReceiveString());  // error message
            }
        }
        public void NegotiateSecuritySuccessTest()
        {
            using (var stream = new TestStream())
            {
                // Have the client send authentication method 'None', which is what the server expects
                VncStream clientStream = new VncStream(stream.Input);
                clientStream.SendByte((byte)AuthenticationMethod.None);
                stream.Input.Position = 0;

                var session = new VncServerSession();
                session.Connect(stream, null, startThread: false);

                Assert.True(session.NegotiateSecurity(new AuthenticationMethod[] { AuthenticationMethod.None }));

                VncStream serverStream = new VncStream(stream.Output);
                stream.Output.Position = 0;

                // Server will have offered 1 authentication method, and successfully authenticated
                // the client
                Assert.Equal(1, serverStream.ReceiveByte());                               // 1 authentication method offered
                Assert.Equal((byte)AuthenticationMethod.None, serverStream.ReceiveByte()); // The authentication method offered
                Assert.Equal(0u, serverStream.ReceiveUInt32BE());                          // authentication succeeded
            }
        }
        public void NegotiateSecurityNoSecurityTypesTest()
        {
            using (var stream = new TestStream())
            {
                var session = new VncServerSession();
                session.Connect(stream, null, startThread: false);

                Assert.False(session.NegotiateSecurity(Array.Empty <AuthenticationMethod>()));

                VncStream serverStream = new VncStream(stream.Output);
                stream.Output.Position = 0;

                // Server should have sent a zero-length array, and a message explaining
                // the disconnect reason
                Assert.Equal(0, serverStream.ReceiveByte());
                Assert.Equal("The server and client could not agree on any authentication method.", serverStream.ReceiveString());
            }
        }
        public void SetDesktopSizeTest()
        {
            var framebuffer1 = new VncFramebuffer("test-1", 100, 200, VncPixelFormat.RGB32);
            var framebuffer2 = new VncFramebuffer("test-2", 200, 400, VncPixelFormat.RGB32);
            var framebuffer  = framebuffer1;

            var framebufferSourceMock = new Mock <IVncFramebufferSource>(MockBehavior.Strict);

            framebufferSourceMock
            .Setup(m => m.SetDesktopSize(200, 300))
            .Returns(ExtendedDesktopSizeStatus.Success)
            .Callback(() => { framebuffer = framebuffer2; });

            framebufferSourceMock
            .Setup(m => m.Capture())
            .Returns(() => framebuffer);

            using (var stream = new TestStream())
            {
                VncStream clientStream = new VncStream(stream.Input);

                // Negotiating the dessktop size
                clientStream.SendByte(0); // share desktop setting

                // Send a SetDesktopSize request
                clientStream.SendByte((byte)VncMessageType.SetDesktopSize);
                clientStream.SendByte(0);       // padding
                clientStream.SendUInt16BE(200); // width
                clientStream.SendUInt16BE(300); // height
                clientStream.SendByte(1);       // number of screens
                clientStream.SendByte(0);       // padding
                clientStream.SendUInt32BE(1);   // screen id
                clientStream.SendUInt16BE(0);   // x position
                clientStream.SendUInt16BE(0);   // x position
                clientStream.SendUInt16BE(200); // width
                clientStream.SendUInt16BE(300); // height
                clientStream.SendUInt32BE(0);   // flags

                stream.Input.Position = 0;

                var session = new VncServerSession();
                session.SetFramebufferSource(framebufferSourceMock.Object);
                session.Connect(stream, null, startThread: false);

                // Negotiate the desktop
                session.NegotiateDesktop();
                Assert.Equal(VncPixelFormat.RGB32, session.ClientPixelFormat);

                // Handle the SetDesktopSize request
                session.HandleMessage();

                VncStream serverStream = new VncStream(stream.Output);
                stream.Output.Position = 0;

                // Desktop negotiation result
                Assert.Equal(100, serverStream.ReceiveUInt16BE());
                Assert.Equal(200, serverStream.ReceiveUInt16BE());
                var format = serverStream.Receive(16);
                Assert.Equal("test-1", serverStream.ReceiveString());

                // SetDesktopSize result
                Assert.Equal(0, serverStream.ReceiveUInt16BE());                                         // Update rectangle request
                Assert.Equal(1, serverStream.ReceiveUInt16BE());                                         // 1 rectangle;

                Assert.Equal((ushort)ExtendedDesktopSizeReason.Client, serverStream.ReceiveUInt16BE());  // x
                Assert.Equal((ushort)ExtendedDesktopSizeStatus.Success, serverStream.ReceiveUInt16BE()); // y
                Assert.Equal(100, serverStream.ReceiveUInt16BE());                                       // width
                Assert.Equal(200, serverStream.ReceiveUInt16BE());                                       // height

                Assert.Equal((int)VncEncoding.ExtendedDesktopSize, (int)serverStream.ReceiveUInt32BE()); // encoding

                Assert.Equal(1u, serverStream.ReceiveByte());                                            // Number of screens
                serverStream.Receive(3);                                                                 // Padding
                Assert.Equal(0u, serverStream.ReceiveUInt32BE());                                        // screen ID
                Assert.Equal(0u, serverStream.ReceiveUInt16BE());                                        // x-position
                Assert.Equal(0u, serverStream.ReceiveUInt16BE());                                        // y-position
                Assert.Equal(100u, serverStream.ReceiveUInt16BE());                                      // width
                Assert.Equal(200u, serverStream.ReceiveUInt16BE());                                      // height
                Assert.Equal(0u, serverStream.ReceiveUInt32BE());                                        // flags

                Assert.Equal(stream.Output.Length, stream.Output.Position);
                Assert.Equal(stream.Input.Length, stream.Input.Position);
            }
        }
        void ThreadMain()
        {
            _requester = new Utility.PeriodicThread();

            try
            {
                InitFramebufferEncoder();

                AuthenticationMethod[] methods;
                NegotiateVersion(out methods);
                NegotiateSecurity(methods);
                NegotiateDesktop();//绘画的桌面
                NegotiateEncodings();

                _requester.Start(FramebufferSendChanges, () => MaxUpdateRate, false);

                IsConnected = true; OnConnected();

                while (true)
                {
                    var command = _c.ReceiveByte();

                    switch (command)
                    {
                    case 0:
                        HandleSetPixelFormat();
                        break;

                    case 2:
                        HandleSetEncodings();
                        break;

                    case 3:
                        HandleFramebufferUpdateRequest();
                        break;

                    case 4:
                        HandleKeyEvent();
                        break;

                    case 5:
                        HandlePointerEvent();
                        break;

                    case 6:
                        HandleReceiveClipboardData();
                        break;

                    default:
                        VncStream.Require(false, "Unsupported command.",
                                          VncFailureReason.UnrecognizedProtocolElement);
                        break;
                    }
                }
            }
            catch (ObjectDisposedException ex)
            {
            }
            catch (IOException ex)
            {
            }
            catch (VncException ex)
            {
                //Vnc错误
            }

            _requester.Stop();

            _c.Stream = null;
            if (IsConnected)
            {
                IsConnected = false; OnClosed();
            }
            else
            {
                OnConnectionFailed();
            }
        }