public VncReadMessageBody ReadServerMessage()
        {
            if (m_readingServerMessage)
            {
                return(null);
            }

            m_readingServerMessage = true;
            try
            {
                var readBody = VncComm.ReadServerMessage(m_readStream,
                                                         m_serverInitBody.ServerPixelFormat.BytesPerPixel,
                                                         m_serverInitBody.ServerPixelFormat.BigEndianFlag);

                // Set after WriteFramebufferUpdateRequest to prevent the excess data
                VncReadMessageBody retBody = null;
                var messageType            = (VncEnum.MessageTypeServerToClient)readBody[0];
                if (messageType == VncEnum.MessageTypeServerToClient.FramebufferUpdate)
                {
                    var encodeList = VncEncodeFactory.CreateVncEncodeFromBinary(readBody,
                                                                                m_serverInitBody.ServerPixelFormat.BytesPerPixel,
                                                                                m_serverInitBody.ServerPixelFormat.BigEndianFlag,
                                                                                m_zrleReader);

                    // Draw to canvas
                    lock (CanvasLock)
                    {
                        foreach (var e in encodeList)
                        {
                            // Draw to canvas
                            IVncPixelGetter pixelGetter = (e.EncodeType == VncEnum.EncodeType.ZRLE) ? m_pixelGetterZrle : m_pixelGetterNormal;
                            e.Draw(pixelGetter, m_canvas);
                        }
                    }

                    retBody = new VncReadMessageBody(messageType, encodeList, null);
                }
                else if (messageType == VncEnum.MessageTypeServerToClient.SetColorMapEntries)
                {
                    var colorMap = new VncSetColorMapEntriesBody(readBody);
                    m_pixelGetterNormal.SetColorMap(colorMap);
                    retBody = new VncReadMessageBody(messageType, null, colorMap);
                }

                onRead(new VncReadEventArgs(readBody, retBody));
                return(retBody);
            }
            catch (Exception a_ex)
            {
                cleanupForDisconnect(a_ex);
                onDisconnected(new VncCauseEventArgs(a_ex));
                return(null);
            }
            finally
            {
                m_readingServerMessage = false;
            }
        }
        public void WritePointerEvent(VncEnum.PointerEventButtonMask a_buttonMask, UInt16 a_x, UInt16 a_y)
        {
            if (!ClientConfig.IsSendPointer)
            {
                return;
            }

            try
            {
                VncComm.WritePointerEvent(m_writeStream, a_buttonMask, a_x, a_y);
            }
            catch (Exception a_ex)
            {
                cleanupForDisconnect(a_ex);
                onDisconnected(new VncCauseEventArgs(a_ex));
            }
        }
        public void WriteKeyEvent(VncEnum.KeyEventDownFlag a_downFlag, UInt32 a_key)
        {
            if (!ClientConfig.IsSendKeyboard)
            {
                return;
            }

            try
            {
                VncComm.WriteKeyEvent(m_writeStream, a_downFlag, a_key);
            }
            catch (Exception a_ex)
            {
                cleanupForDisconnect(a_ex);
                onDisconnected(new VncCauseEventArgs(a_ex));
            }
        }
 public void WriteFramebufferUpdateRequest()
 {
     try
     {
         VncComm.WriteFramebufferUpdateRequest(m_writeStream,
                                               VncEnum.FramebufferUpdateRequestIncremental.Incremental,
                                               0,
                                               0,
                                               m_serverInitBody.FramebufferWidth,
                                               m_serverInitBody.FramebufferHeight);
     }
     catch (Exception a_ex)
     {
         cleanupForDisconnect(a_ex);
         onDisconnected(new VncCauseEventArgs(a_ex));
     }
 }
        public bool ConnectVnc()
        {
            Connecting = true;

            try
            {
                m_tcpClient = new TcpClient();
                m_tcpClient.Connect(ClientConfig.Address, ClientConfig.Port);

                m_readStream  = m_readStreamCreator(m_tcpClient.Client);
                m_writeStream = m_writeStreamCreator(m_tcpClient.Client);

                // ZRLE encoding uses one zlib stream during connection.
                // Therefore, it generates at the timing of VNC connection.
                m_zrleReader?.Dispose();
                m_zrleReader = new ZrleDataReader();

                //-----------------------
                // Handshake
                //-----------------------
                // Server -> (ProtocolVersion) -> Client
                var version = VncComm.ReadProtocolVersion(m_readStream, ClientConfig.ForceVersion);

                // Server <- (ProtocolVersion) <- Client
                VncComm.WriteProtocolVersion(m_writeStream, version);

                // (Security)
                if (version == VncEnum.Version.Version33)
                {
                    // Server -> (Security) -> Client
                    var securityType = VncComm.ReadSecurityType(m_readStream);
                    if (securityType != VncEnum.SecurityType.None &&
                        securityType != VncEnum.SecurityType.VNCAuthentication)
                    {
                        throw new SecurityException($"VNC Version is 3.3. Security type is {securityType}.");
                    }

                    if (securityType == VncEnum.SecurityType.VNCAuthentication)
                    {
                        // Server -> (VNC Authentication Challenge) -> Client
                        var challenge = VncComm.ReadVncChallange(m_readStream);

                        // Server <- (VNC Authentication Response) <- Client
                        byte[] response = encryptChallenge(ClientConfig.Password, challenge);
                        VncComm.WriteVncResponse(m_writeStream, response);

                        // Server -> (Security Result) -> Client
                        VncComm.ReadSecurityResult(m_readStream, version); // Result is checked in method. So don't check here,
                    }
                }
                else
                {
                    // Server -> (SecurityTypes) -> Client
                    var securityTypes = VncComm.ReadSecurityTypes(m_readStream);

                    if (securityTypes.Contains(VncEnum.SecurityType.None))
                    {
                        // Server <- (SecurityType) <- Client
                        VncComm.WriteSecurityType(m_writeStream, VncEnum.SecurityType.None);

                        if (version == VncEnum.Version.Version38)
                        {
                            // Server -> (Security Result) -> Client
                            VncComm.ReadSecurityResult(m_readStream, version);
                        }
                    }
                    else if (securityTypes.Contains(VncEnum.SecurityType.VNCAuthentication))
                    {
                        // Server <- (SecurityType) <- Client
                        VncComm.WriteSecurityType(m_writeStream, VncEnum.SecurityType.VNCAuthentication);

                        // Server -> (VNC Authentication Challenge) -> Client
                        var challenge = VncComm.ReadVncChallange(m_readStream);

                        // Server <- (VNC Authentication Response) <- Client
                        byte[] response = encryptChallenge(ClientConfig.Password, challenge);
                        VncComm.WriteVncResponse(m_writeStream, response);

                        // Server -> (Security Result) -> Client
                        VncComm.ReadSecurityResult(m_readStream, version);
                    }
                    else
                    {
                        throw new SecurityException($"Unknown security-types. Server can use [{string.Join(",", securityTypes)}].");
                    }
                }

                //-----------------------
                // Initial Message
                //-----------------------
                // Server <- (ClientInit) <- Client
                VncComm.WriteClientInit(m_writeStream, VncEnum.SharedFlag.Share);

                // Server -> (ServerInit) -> Client
                m_serverInitBody = VncComm.ReadServerInit(m_readStream);

                //-----------------------
                // InitialSettings
                //-----------------------
                // Server <- (SetEncodings) <- Client
                VncComm.WriteSetEncodings(m_writeStream, ClientConfig.Encodings);

                // Server <- (SetPixelFormat) <- Client
                if (ClientConfig.IsColourSpecified)
                {
                    var pixelFormat = new PixelFormat(ClientConfig.SpecifiedColour.BytesPerPixel,
                                                      ClientConfig.SpecifiedColour.Depth,
                                                      m_serverInitBody.ServerPixelFormat.BigEndianFlag,
                                                      ClientConfig.SpecifiedColour.TrueColorFlag,
                                                      ClientConfig.SpecifiedColour.RedMax,
                                                      ClientConfig.SpecifiedColour.GreenMax,
                                                      ClientConfig.SpecifiedColour.BlueMax,
                                                      ClientConfig.SpecifiedColour.RedShift,
                                                      ClientConfig.SpecifiedColour.GreenShift,
                                                      ClientConfig.SpecifiedColour.BlueShift);
                    m_serverInitBody = new VncServerInitBody(m_serverInitBody.FramebufferWidth,
                                                             m_serverInitBody.FramebufferHeight,
                                                             pixelFormat,
                                                             m_serverInitBody.NameString);
                    VncComm.WriteSetPixelFormat(m_writeStream, m_serverInitBody.ServerPixelFormat);
                }

                //-----------------------
                // Refresh Framebuffer
                //-----------------------
                // Server <- (Refresh Framebuffer) <- Client
                VncComm.WriteFramebufferUpdateRequest(m_writeStream,
                                                      VncEnum.FramebufferUpdateRequestIncremental.UpdateAll,
                                                      0,
                                                      0,
                                                      m_serverInitBody.FramebufferWidth,
                                                      m_serverInitBody.FramebufferHeight);

                // Create Data
                m_pixelGetterNormal = VncPixelGetterFactory.CreateVncPixelGetter(m_serverInitBody.ServerPixelFormat, VncEnum.EncodeType.Raw);
                m_pixelGetterZrle   = VncPixelGetterFactory.CreateVncPixelGetter(m_serverInitBody.ServerPixelFormat, VncEnum.EncodeType.ZRLE);

                m_canvas?.Dispose();
                m_canvas = new MatOfByte3(m_serverInitBody.FramebufferHeight, m_serverInitBody.FramebufferWidth);

                // Successful connection
                m_connected = true;
                onConnected();
            }
            catch (Exception a_ex)
            {
                cleanupForDisconnect(a_ex);
                onConnectFailed(new VncCauseEventArgs(a_ex));
            }
            finally
            {
                Connecting = false;
            }

            return(m_connected);
        }