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); }
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); }