void ClientConnection::ReadCopyRect(rfbFramebufferUpdateRectHeader *pfburh) { rfbCopyRect cr; double tBlitStart; ReadExact((char *) &cr, sz_rfbCopyRect); cr.srcX = Swap16IfLE(cr.srcX); cr.srcY = Swap16IfLE(cr.srcY); // If *Cursor encoding is used, we should extend our "cursor lock area" // (previously set to destination rectangle) to the source rect as well. SoftCursorLockArea(cr.srcX, cr.srcY, pfburh->r.w, pfburh->r.h); omni_mutex_lock l(m_bitmapdcMutex); ObjectSelector b(m_hBitmapDC, m_hBitmap); PaletteSelector p(m_hBitmapDC, m_hPalette); if (m_opts.m_benchFile) tBlitStart = getTime(); if (!BitBlt(m_hBitmapDC, pfburh->r.x, pfburh->r.y, pfburh->r.w, pfburh->r.h, m_hBitmapDC, cr.srcX, cr.srcY, SRCCOPY)) vnclog.Print(0, "Error in blit in ClientConnection::CopyRect\n"); if (m_opts.m_benchFile) tBlit += getTime() - tBlitStart; }
void ClientConnection::ReadUltraRect(rfbFramebufferUpdateRectHeader *pfburh) { UINT numpixels = pfburh->r.w * pfburh->r.h; // this assumes at least one byte per pixel. Naughty. UINT numRawBytes = numpixels * m_minPixelBytes; UINT numCompBytes; lzo_uint new_len; rfbZlibHeader hdr; // Read in the rfbZlibHeader omni_mutex_lock l(m_bitmapdcMutex); ReadExact((char *)&hdr, sz_rfbZlibHeader); numCompBytes = Swap32IfLE(hdr.nBytes); // Read in the compressed data CheckBufferSize(numCompBytes); ReadExact(m_netbuf, numCompBytes); CheckZlibBufferSize(numRawBytes); lzo1x_decompress((BYTE*)m_netbuf,numCompBytes,(BYTE*)m_zlibbuf,&new_len,NULL); SoftCursorLockArea(pfburh->r.x, pfburh->r.y,pfburh->r.w,pfburh->r.h); if (!Check_Rectangle_borders(pfburh->r.x, pfburh->r.y,pfburh->r.w,pfburh->r.h)) return; if (m_DIBbits) ConvertAll(pfburh->r.w,pfburh->r.h,pfburh->r.x, pfburh->r.y,m_myFormat.bitsPerPixel/8,(BYTE *)m_zlibbuf,(BYTE *)m_DIBbits,m_si.framebufferWidth); }
void ClientConnection::ReadCopyRect(rfbFramebufferUpdateRectHeader *pfburh) { rfbCopyRect cr; ReadExact((char *) &cr, sz_rfbCopyRect); cr.srcX = Swap16IfLE(cr.srcX); cr.srcY = Swap16IfLE(cr.srcY); // By sure the rect is insite the border memcopy does not like it if (!Check_Rectangle_borders(pfburh->r.x, pfburh->r.y, pfburh->r.w, pfburh->r.h)) return; if (!Check_Rectangle_borders(cr.srcX, cr.srcY, pfburh->r.w, pfburh->r.h)) return; // tight If *Cursor encoding is used, we should extend our "cursor lock area" // (previously set to destination rectangle) to the source rect as well. SoftCursorLockArea(cr.srcX, cr.srcY, pfburh->r.w, pfburh->r.h); if (m_DIBbits) { omni_mutex_lock l(m_bitmapdcMutex); int bytesPerInputRow = m_si.framebufferWidth * m_myFormat.bitsPerPixel/8; int bytesPerOutputRow = pfburh->r.w * m_myFormat.bitsPerPixel/8; int OutputHeight=pfburh->r.h; BYTE *sourcepos,*iptr,*destpos,*optr; if (cr.srcY<=pfburh->r.y) { { destpos = (BYTE*)m_DIBbits + (bytesPerInputRow * (pfburh->r.y+pfburh->r.h-1))+(pfburh->r.x * m_myFormat.bitsPerPixel/8); sourcepos = (BYTE*)m_DIBbits + (bytesPerInputRow * (cr.srcY+pfburh->r.h-1))+((cr.srcX) * m_myFormat.bitsPerPixel/8); iptr=sourcepos; optr=destpos; while (OutputHeight > 0) { memcpy(optr, iptr, bytesPerOutputRow); iptr -= bytesPerInputRow; optr -= bytesPerInputRow; OutputHeight--; } } } else if (cr.srcY>pfburh->r.y) { { destpos = (BYTE*)m_DIBbits + (bytesPerInputRow * pfburh->r.y)+(pfburh->r.x * m_myFormat.bitsPerPixel/8); sourcepos = (BYTE*)m_DIBbits + (bytesPerInputRow * (cr.srcY))+((cr.srcX) * m_myFormat.bitsPerPixel/8); iptr=sourcepos; optr=destpos; while (OutputHeight > 0) { memcpy(optr, iptr, bytesPerOutputRow); iptr += bytesPerInputRow; optr += bytesPerInputRow; OutputHeight--; } } } } }
// // sf@2002 // - Read a cache rects zipped block coming from the server // - Restore all these cache rects on the screen void ClientConnection::ReadCacheZip(rfbFramebufferUpdateRectHeader *pfburh,HRGN *prgn) { UINT nNbCacheRects = pfburh->r.x; UINT numRawBytes = nNbCacheRects * sz_rfbRectangle; numRawBytes += (numRawBytes/100) + 8; UINT numCompBytes; rfbZlibHeader hdr; // Read in the rfbZlibHeader ReadExact((char *)&hdr, sz_rfbZlibHeader); numCompBytes = Swap32IfLE(hdr.nBytes); // Check the net buffer CheckBufferSize(numCompBytes); // Read the compressed data ReadExact((char *)m_netbuf, numCompBytes); // Verify buffer space for cache rects list CheckZipBufferSize(numRawBytes); int nRet = uncompress((unsigned char*)m_zipbuf,// Dest (unsigned long*)&numRawBytes,// Dest len (unsigned char*)m_netbuf, // Src numCompBytes // Src len ); if (nRet != 0) { return; } // Read all the cache rects rfbRectangle theRect; BYTE* p = m_zipbuf; for (UINT i = 0 ; i < nNbCacheRects; i++) { memcpy((BYTE*)&theRect, p, sz_rfbRectangle); p += sz_rfbRectangle; RECT cacherect; cacherect.left = Swap16IfLE(theRect.x); cacherect.right = Swap16IfLE(theRect.x) + Swap16IfLE(theRect.w); cacherect.top = Swap16IfLE(theRect.y); cacherect.bottom = Swap16IfLE(theRect.y) + Swap16IfLE(theRect.h); SoftCursorLockArea(cacherect.left, cacherect.top, cacherect.right - cacherect.left, cacherect.bottom - cacherect.top); RestoreArea(cacherect); InvalidateRegion(&cacherect,prgn); } }
void ClientConnection::ReadUltraZip(rfbFramebufferUpdateRectHeader *pfburh,HRGN *prgn) { UINT nNbCacheRects = pfburh->r.x; UINT numRawBytes = pfburh->r.y+pfburh->r.w*65535; UINT numCompBytes; lzo_uint new_len; rfbZlibHeader hdr; // Read in the rfbZlibHeader omni_mutex_lock l(m_bitmapdcMutex); ReadExact((char *)&hdr, sz_rfbZlibHeader); numCompBytes = Swap32IfLE(hdr.nBytes); // Check the net buffer CheckBufferSize(numCompBytes); // Read the compressed data ReadExact((char *)m_netbuf, numCompBytes); // Verify buffer space for cache rects list CheckZlibBufferSize(numRawBytes+500); lzo1x_decompress((BYTE*)m_netbuf,numCompBytes,(BYTE*)m_zlibbuf,&new_len,NULL); BYTE* pzipbuf = m_zlibbuf; for (UINT i = 0 ; i < nNbCacheRects; i++) { rfbFramebufferUpdateRectHeader surh; memcpy((char *) &surh,pzipbuf, sz_rfbFramebufferUpdateRectHeader); surh.r.x = Swap16IfLE(surh.r.x); surh.r.y = Swap16IfLE(surh.r.y); surh.r.w = Swap16IfLE(surh.r.w); surh.r.h = Swap16IfLE(surh.r.h); surh.encoding = Swap32IfLE(surh.encoding); pzipbuf += sz_rfbFramebufferUpdateRectHeader; RECT rect; rect.left = surh.r.x; rect.right = surh.r.x + surh.r.w; rect.top = surh.r.y; rect.bottom = surh.r.y + surh.r.h; //border check if (!Check_Rectangle_borders(rect.left,rect.top,surh.r.w,surh.r.h)) return; SoftCursorLockArea(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top); if ( surh.encoding==rfbEncodingRaw) { UINT numpixels = surh.r.w * surh.r.h; if (m_DIBbits) ConvertAll(surh.r.w,surh.r.h,surh.r.x, surh.r.y,m_myFormat.bitsPerPixel/8,(BYTE *)pzipbuf,(BYTE *)m_DIBbits,m_si.framebufferWidth); pzipbuf +=numpixels*m_myFormat.bitsPerPixel/8; if (!m_opts.m_Directx)InvalidateRegion(&rect,prgn); } } }
Bool HandleRFBServerMessage() { rfbServerToClientMsg msg; if (!ReadFromRFBServer((char *)&msg, 1)) return False; switch (msg.type) { case rfbSetColourMapEntries: { int i; CARD16 rgb[3]; XColor xc; if (!ReadFromRFBServer(((char *)&msg) + 1, sz_rfbSetColourMapEntriesMsg - 1)) return False; msg.scme.firstColour = Swap16IfLE(msg.scme.firstColour); msg.scme.nColours = Swap16IfLE(msg.scme.nColours); for (i = 0; i < msg.scme.nColours; i++) { if (!ReadFromRFBServer((char *)rgb, 6)) return False; xc.pixel = msg.scme.firstColour + i; xc.red = Swap16IfLE(rgb[0]); xc.green = Swap16IfLE(rgb[1]); xc.blue = Swap16IfLE(rgb[2]); xc.flags = DoRed|DoGreen|DoBlue; XStoreColor(dpy, cmap, &xc); } break; } case rfbFramebufferUpdate: { rfbFramebufferUpdateRectHeader rect; int linesToRead; int bytesPerLine; int i; int usecs; if (!ReadFromRFBServer(((char *)&msg.fu) + 1, sz_rfbFramebufferUpdateMsg - 1)) return False; msg.fu.nRects = Swap16IfLE(msg.fu.nRects); for (i = 0; i < msg.fu.nRects; i++) { if (!ReadFromRFBServer((char *)&rect, sz_rfbFramebufferUpdateRectHeader)) return False; rect.encoding = Swap32IfLE(rect.encoding); if (rect.encoding == rfbEncodingLastRect) break; rect.r.x = Swap16IfLE(rect.r.x); rect.r.y = Swap16IfLE(rect.r.y); rect.r.w = Swap16IfLE(rect.r.w); rect.r.h = Swap16IfLE(rect.r.h); if (rect.encoding == rfbEncodingXCursor || rect.encoding == rfbEncodingRichCursor) { if (!HandleCursorShape(rect.r.x, rect.r.y, rect.r.w, rect.r.h, rect.encoding)) { return False; } continue; } if (rect.encoding == rfbEncodingPointerPos) { if (!HandleCursorPos(rect.r.x, rect.r.y)) { return False; } continue; } if ((rect.r.x + rect.r.w > si.framebufferWidth) || (rect.r.y + rect.r.h > si.framebufferHeight)) { fprintf(stderr,"Rect too large: %dx%d at (%d, %d)\n", rect.r.w, rect.r.h, rect.r.x, rect.r.y); return False; } if (rect.r.h * rect.r.w == 0) { fprintf(stderr,"Zero size rect - ignoring\n"); continue; } /* If RichCursor encoding is used, we should prevent collisions between framebuffer updates and cursor drawing operations. */ SoftCursorLockArea(rect.r.x, rect.r.y, rect.r.w, rect.r.h); switch (rect.encoding) { case rfbEncodingRaw: bytesPerLine = rect.r.w * myFormat.bitsPerPixel / 8; linesToRead = BUFFER_SIZE / bytesPerLine; while (rect.r.h > 0) { if (linesToRead > rect.r.h) linesToRead = rect.r.h; if (!ReadFromRFBServer(buffer,bytesPerLine * linesToRead)) return False; CopyDataToScreen(buffer, rect.r.x, rect.r.y, rect.r.w, linesToRead); rect.r.h -= linesToRead; rect.r.y += linesToRead; } break; case rfbEncodingCopyRect: { rfbCopyRect cr; if (!ReadFromRFBServer((char *)&cr, sz_rfbCopyRect)) return False; cr.srcX = Swap16IfLE(cr.srcX); cr.srcY = Swap16IfLE(cr.srcY); /* If RichCursor encoding is used, we should extend our "cursor lock area" (previously set to destination rectangle) to the source rectangle as well. */ SoftCursorLockArea(cr.srcX, cr.srcY, rect.r.w, rect.r.h); if (appData.copyRectDelay != 0) { XFillRectangle(dpy, desktopWin, srcGC, cr.srcX, cr.srcY, rect.r.w, rect.r.h); #if VNC_CAPTURE myxfillrec(dpy, srcGC, cr.srcX, cr.srcY, rect.r.w, rect.r.h); #endif XFillRectangle(dpy, desktopWin, dstGC, rect.r.x, rect.r.y, rect.r.w, rect.r.h); #if VNC_CAPTURE myxfillrec(dpy, dstGC, cr.srcX, cr.srcY, rect.r.w, rect.r.h); #endif XSync(dpy,False); usleep(appData.copyRectDelay * 1000); XFillRectangle(dpy, desktopWin, dstGC, rect.r.x, rect.r.y, rect.r.w, rect.r.h); #if VNC_CAPTURE myxfillrec(dpy, dstGC, rect.r.x, rect.r.y, rect.r.w, rect.r.h); #endif XFillRectangle(dpy, desktopWin, srcGC, cr.srcX, cr.srcY, rect.r.w, rect.r.h); #if VNC_CAPTURE myxfillrec(dpy, srcGC, cr.srcX, cr.srcY, rect.r.w, rect.r.h); #endif } XCopyArea(dpy, desktopWin, desktopWin, gc, cr.srcX, cr.srcY, rect.r.w, rect.r.h, rect.r.x, rect.r.y); #if VNC_CAPTURE myxcparea(dpy, gc, cr.srcX, cr.srcY, rect.r.w, rect.r.h,rect.r.x,rect.r.y); #endif break; } case rfbEncodingRRE: { switch (myFormat.bitsPerPixel) { case 8: if (!HandleRRE8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; case 16: if (!HandleRRE16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; case 32: if (!HandleRRE32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; } break; } case rfbEncodingCoRRE: { switch (myFormat.bitsPerPixel) { case 8: if (!HandleCoRRE8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; case 16: if (!HandleCoRRE16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; case 32: if (!HandleCoRRE32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; } break; } case rfbEncodingHextile: { switch (myFormat.bitsPerPixel) { case 8: if (!HandleHextile8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; case 16: if (!HandleHextile16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; case 32: if (!HandleHextile32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; } break; } case rfbEncodingZlib: { switch (myFormat.bitsPerPixel) { case 8: if (!HandleZlib8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; case 16: if (!HandleZlib16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; case 32: if (!HandleZlib32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; } break; } case rfbEncodingTight: { switch (myFormat.bitsPerPixel) { case 8: if (!HandleTight8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; case 16: if (!HandleTight16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; case 32: if (!HandleTight32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; } break; } default: fprintf(stderr,"Unknown rect encoding %d\n", (int)rect.encoding); return False; } /* Now we may discard "soft cursor locks". */ SoftCursorUnlockScreen(); } #ifdef MITSHM /* if using shared memory PutImage, make sure that the X server has updated its framebuffer before we reuse the shared memory. This is mainly to avoid copyrect using invalid screen contents - not sure if we'd need it otherwise. */ if (appData.useShm) XSync(dpy, False); #endif if (!SendIncrementalFramebufferUpdateRequest()) return False; break; } case rfbBell: { Window toplevelWin; XBell(dpy, 0); if (appData.raiseOnBeep) { toplevelWin = XtWindow(toplevel); XMapRaised(dpy, toplevelWin); } break; } case rfbServerCutText: { if (!ReadFromRFBServer(((char *)&msg) + 1, sz_rfbServerCutTextMsg - 1)) return False; msg.sct.length = Swap32IfLE(msg.sct.length); if (serverCutText) free(serverCutText); serverCutText = malloc(msg.sct.length+1); if (!ReadFromRFBServer(serverCutText, msg.sct.length)) return False; serverCutText[msg.sct.length] = 0; newServerCutText = True; break; } default: fprintf(stderr,"Unknown message type %d from VNC server\n",msg.type); return False; } return True; }
Bool HandleRFBServerMessage() { rfbServerToClientMsg msg; if (!ReadFromRFBServer((char *)&msg, 1)) return False; switch (msg.type) { case rfbSetColourMapEntries: { fprintf(stderr, "Received unsupported rfbSetColourMapEntries\n"); return False; /* unsupported */ } case rfbFramebufferUpdate: { rfbFramebufferUpdateRectHeader rect; int linesToRead; int bytesPerLine; int i; if (!ReadFromRFBServer(((char *)&msg.fu) + 1, sz_rfbFramebufferUpdateMsg - 1)) return False; msg.fu.nRects = Swap16IfLE(msg.fu.nRects); for (i = 0; i < msg.fu.nRects; i++) { if (!ReadFromRFBServer((char *)&rect, sz_rfbFramebufferUpdateRectHeader)) return False; rect.r.x = Swap16IfLE(rect.r.x); rect.r.y = Swap16IfLE(rect.r.y); rect.r.w = Swap16IfLE(rect.r.w); rect.r.h = Swap16IfLE(rect.r.h); rect.encoding = Swap32IfLE(rect.encoding); if (rect.encoding == rfbEncodingXCursor) { if (!HandleCursorShape(rect.r.x, rect.r.y, rect.r.w, rect.r.h, rfbEncodingXCursor)) { return False; } continue; } if (rect.encoding == rfbEncodingRichCursor) { if (!HandleCursorShape(rect.r.x, rect.r.y, rect.r.w, rect.r.h, rfbEncodingRichCursor)) { return False; } continue; } if (rect.encoding == rfbEncodingPointerPos) { if (!HandleCursorPos(rect.r.x, rect.r.y)) { return False; } appData.gotCursorPos = 1; continue; } if ((rect.r.x + rect.r.w > si.framebufferWidth) || (rect.r.y + rect.r.h > si.framebufferHeight)) { fprintf(stderr,"Rect too large: %dx%d at (%d, %d)\n", rect.r.w, rect.r.h, rect.r.x, rect.r.y); return False; } if ((rect.r.h * rect.r.w) == 0) { fprintf(stderr,"Zero size rect - ignoring\n"); continue; } /* If RichCursor encoding is used, we should prevent collisions between framebuffer updates and cursor drawing operations. */ SoftCursorLockArea(rect.r.x, rect.r.y, rect.r.w, rect.r.h); switch (rect.encoding) { case rfbEncodingRaw: bytesPerLine = rect.r.w * myFormat.bitsPerPixel / 8; linesToRead = BUFFER_SIZE / bytesPerLine; while (rect.r.h > 0) { if (linesToRead > rect.r.h) linesToRead = rect.r.h; if (!ReadFromRFBServer(buffer,bytesPerLine * linesToRead)) return False; CopyDataToScreen(buffer, rect.r.x, rect.r.y, rect.r.w, linesToRead); rect.r.h -= linesToRead; rect.r.y += linesToRead; } break; case rfbEncodingCopyRect: { rfbCopyRect cr; char *buffer; if (!ReadFromRFBServer((char *)&cr, sz_rfbCopyRect)) return False; if (!BufferWritten()) { /* Ignore attempts to do copy-rect when we have nothing to * copy from. */ break; } cr.srcX = Swap16IfLE(cr.srcX); cr.srcY = Swap16IfLE(cr.srcY); /* If RichCursor encoding is used, we should extend our "cursor lock area" (previously set to destination rectangle) to the source rectangle as well. */ SoftCursorLockArea(cr.srcX, cr.srcY, rect.r.w, rect.r.h); buffer = CopyScreenToData(cr.srcX, cr.srcY, rect.r.w, rect.r.h); CopyDataToScreen(buffer, rect.r.x, rect.r.y, rect.r.w, rect.r.h); free(buffer); break; } case rfbEncodingRRE: { if (!HandleRRE32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; } case rfbEncodingCoRRE: { if (!HandleCoRRE32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; } case rfbEncodingHextile: { if (!HandleHextile32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; } case rfbEncodingZlib: { if (!HandleZlib32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; } case rfbEncodingTight: { if (!HandleTight32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; } case rfbEncodingZRLE: if (!zrleDecode(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; default: fprintf(stderr,"Unknown rect encoding %d\n", (int)rect.encoding); return False; } /* Now we may discard "soft cursor locks". */ SoftCursorUnlockScreen(); /* Done. Save the screen image. */ } /* RealVNC sometimes returns an initial black screen. */ if (BufferIsBlank() && appData.ignoreBlank) { if (!appData.quiet && appData.ignoreBlank != 1) { /* user did not specify either -quiet or -ignoreblank */ fprintf(stderr, "Warning: discarding received blank screen (use -allowblank to accept,\n or -ignoreblank to suppress this message)\n"); appData.ignoreBlank = 1; } RequestNewUpdate(); } else { return False; } break; } case rfbBell: /* ignore */ break; case rfbServerCutText: { if (!ReadFromRFBServer(((char *)&msg) + 1, sz_rfbServerCutTextMsg - 1)) return False; msg.sct.length = Swap32IfLE(msg.sct.length); if (serverCutText) free(serverCutText); serverCutText = malloc(msg.sct.length+1); if (!ReadFromRFBServer(serverCutText, msg.sct.length)) return False; serverCutText[msg.sct.length] = 0; newServerCutText = True; break; } default: fprintf(stderr,"Unknown message type %d from VNC server\n",msg.type); return False; } return True; }