예제 #1
0
 public VncEncodeZrle(UInt16 a_x, UInt16 a_y, UInt16 a_width, UInt16 a_height, byte[] a_zlibData, int a_offset, int a_length, ZrleDataReader a_zrleReader)
 {
     X            = a_x;
     Y            = a_y;
     Width        = a_width;
     Height       = a_height;
     m_zlibData   = a_zlibData;
     m_offset     = a_offset;
     m_length     = a_length;
     m_zrleReader = a_zrleReader;
     EncodeType   = VncEnum.EncodeType.ZRLE;
 }
        private static (VncEncodeAbstract encode, int length) createVncEncodeFromBinarySub(byte[] a_body, int a_basePos, byte a_bytesPerPixel, bool a_isBigendian, ZrleDataReader a_zrleReader)
        {
            UInt16 x          = BigEndianBitConverter.ToUInt16(a_body, a_basePos + 0);
            UInt16 y          = BigEndianBitConverter.ToUInt16(a_body, a_basePos + 2);
            UInt16 w          = BigEndianBitConverter.ToUInt16(a_body, a_basePos + 4);
            UInt16 h          = BigEndianBitConverter.ToUInt16(a_body, a_basePos + 6);
            var    encodeType = (VncEnum.EncodeType)BigEndianBitConverter.ToInt32(a_body, a_basePos + 8);

            int offset;

            switch (encodeType)
            {
            case VncEnum.EncodeType.Raw:
                return(new VncEncodeRaw(x, y, w, h, a_body, a_basePos + 12), 12 + w * h * a_bytesPerPixel);

            case VncEnum.EncodeType.CopyRect:
                UInt16 sx = BigEndianBitConverter.ToUInt16(a_body, a_basePos + 12);
                UInt16 sy = BigEndianBitConverter.ToUInt16(a_body, a_basePos + 14);
                return(new VncEncodeCopyRect(x, y, w, h, sx, sy), 12 + 4);

            case VncEnum.EncodeType.RRE:
                // Read header
                UInt32 numberOfSubrectangles = BigEndianBitConverter.ToUInt32(a_body, a_basePos + 12);
                byte[] backgroundPixelValue  = VncPixelByteGetter.GetPixelByte(a_bytesPerPixel, a_body, a_basePos + 16);

                // Create subrectangles
                int subrectSize   = a_bytesPerPixel + 8;
                var subrectangles = new VncEncodeRreSubrectangle[numberOfSubrectangles];
                for (int i = 0; i < numberOfSubrectangles; ++i)
                {
                    offset = a_basePos + subrectSize * i;
                    byte[] pixel  = VncPixelByteGetter.GetPixelByte(a_bytesPerPixel, a_body, (16 + a_bytesPerPixel) + 0 + offset);
                    UInt16 xpos   = BigEndianBitConverter.ToUInt16(a_body, (16 + a_bytesPerPixel + a_bytesPerPixel) + 0 + offset);
                    UInt16 ypos   = BigEndianBitConverter.ToUInt16(a_body, (16 + a_bytesPerPixel + a_bytesPerPixel) + 2 + offset);
                    UInt16 width  = BigEndianBitConverter.ToUInt16(a_body, (16 + a_bytesPerPixel + a_bytesPerPixel) + 4 + offset);
                    UInt16 height = BigEndianBitConverter.ToUInt16(a_body, (16 + a_bytesPerPixel + a_bytesPerPixel) + 6 + offset);
                    subrectangles[i] = new VncEncodeRreSubrectangle(pixel, xpos, ypos, width, height);
                }

                int len = 12 + (4 + a_bytesPerPixel) + (a_bytesPerPixel + 2 + 2 + 2 + 2) * (int)numberOfSubrectangles;
                return(new VncEncodeRre(x, y, w, h, backgroundPixelValue, subrectangles), len);

            case VncEnum.EncodeType.Hextile:
                int xTileCount = (int)Math.Ceiling(w / 16.0);
                int yTileCount = (int)Math.Ceiling(h / 16.0);
                var hextiles   = new IVncEncodeHextileTile[xTileCount * yTileCount];

                // Loop for each tile
                offset = a_basePos + 12;
                int    index           = 0;
                byte[] backgroundPixel = null;
                byte[] foregroundPixel = null;
                for (int ytile = 0; ytile < yTileCount; ++ytile)
                {
                    int tileHeight = ((ytile == yTileCount - 1) && ((h % 16) != 0)) ? h % 16 : 16;
                    for (int xtile = 0; xtile < xTileCount; ++xtile, ++index)
                    {
                        int tileWidth = ((xtile == xTileCount - 1) && ((w % 16) != 0)) ? w % 16 : 16;

                        // Read header
                        var subencodingMask = new VncEncodeHextileSubencodingMask(a_body[offset]);
                        ++offset;

                        if (subencodingMask.Raw)
                        {
                            // Raw pixel data
                            hextiles[index] = new VncEncodeHextileTileRaw(a_body, offset);
                            offset         += tileWidth * tileHeight * a_bytesPerPixel;
                        }
                        else
                        {
                            // Read BackgroundSpecified if needed
                            if (subencodingMask.BackgroundSpecified)
                            {
                                backgroundPixel = VncPixelByteGetter.GetPixelByte(a_bytesPerPixel, a_body, offset);
                                offset         += a_bytesPerPixel;
                            }

                            // Read ForegroundSpecified if needed
                            if (subencodingMask.ForegroundSpecified)
                            {
                                foregroundPixel = VncPixelByteGetter.GetPixelByte(a_bytesPerPixel, a_body, offset);
                                offset         += a_bytesPerPixel;
                            }

                            // Subrects
                            VncEncodeHextileSubrect[] hextileSubrect;
                            if (subencodingMask.AnySubrects)
                            {
                                // Read number-of-subrectangles
                                byte numberOfSubrectanglesHextile = a_body[offset];
                                ++offset;

                                // Read subrectangle
                                hextileSubrect = new VncEncodeHextileSubrect[numberOfSubrectanglesHextile];
                                if (subencodingMask.SubrectsColored)
                                {
                                    for (int i = 0; i < numberOfSubrectanglesHextile; ++i)
                                    {
                                        hextileSubrect[i] = new VncEncodeHextileSubrect(VncPixelByteGetter.GetPixelByte(a_bytesPerPixel, a_body, offset),
                                                                                        a_body[offset + a_bytesPerPixel],
                                                                                        a_body[offset + a_bytesPerPixel + 1]);
                                        offset += a_bytesPerPixel + 2;
                                    }
                                }
                                else
                                {
                                    for (int i = 0; i < numberOfSubrectanglesHextile; ++i)
                                    {
                                        hextileSubrect[i] = new VncEncodeHextileSubrect(foregroundPixel, a_body[offset + 0], a_body[offset + 1]);
                                        offset           += 2;
                                    }
                                }
                            }
                            else
                            {
                                // Set empty subrects
                                hextileSubrect = new VncEncodeHextileSubrect[0];
                            }

                            hextiles[index] = new VncEncodeHextileTileRre(backgroundPixel, hextileSubrect);
                        }
                    }
                }

                return(new VncEncodeHextile(x, y, w, h, hextiles), offset - a_basePos);

            case VncEnum.EncodeType.ZRLE:
                int zrleLength = BigEndianBitConverter.ToInt32(a_body, a_basePos + 12);
                return(new VncEncodeZrle(x, y, w, h, a_body, a_basePos + 16, zrleLength, a_zrleReader), 12 + 4 + zrleLength);

            case VncEnum.EncodeType.Cursor:
            case VncEnum.EncodeType.DesktopSize:
            default:
                throw new NotSupportedException($"Encode type ({encodeType}) is Not supported.");
            }
        }
        public static List <VncEncodeAbstract> CreateVncEncodeFromBinary(byte[] a_body, byte a_bytesPerPixel, bool a_isBigendian, ZrleDataReader a_zrleReader)
        {
            var vncEncodeList = new List <VncEncodeAbstract>();

            // Message Type(1) - Read padding(1) - number-of-rectangles(2)
            UInt16 numberOfRectangle = BigEndianBitConverter.ToUInt16(a_body, 2);

            // Read rectangles (pos = 4 == Message Type(1) + Read padding(1) + number-of-rectangles(2)
            for (int i = 0, pos = 4; i < numberOfRectangle; ++i)
            {
                var dat = createVncEncodeFromBinarySub(a_body, pos, a_bytesPerPixel, a_isBigendian, a_zrleReader);
                vncEncodeList.Add(dat.encode);
                pos += dat.length;
            }

            return(vncEncodeList);
        }
예제 #4
0
        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);
        }