void blit_raw(tSDL_vnc * vnc, tSDL_vnc_rect rect) { SDL_Rect trec; vnc_to_sdl_rect(&rect, &trec); SDL_LockMutex(vnc->mutex); SDL_LockSurface(vnc->framebuffer); uint32_t * src = vnc->rawbuffer; uint32_t srcpitch = rect.width; uint32_t len = srcpitch * 4; uint32_t pitch = vnc->framebuffer->pitch/4; uint32_t * dest = (uint32_t *)vnc->framebuffer->pixels + (rect.y * pitch) + rect.x; if (srcpitch == pitch) { /* full screen, or at least full width */ memcpy(dest, src, len * rect.height); } else { uint32_t * end = dest + (pitch*rect.height); while (dest < end) { memcpy(dest, src, len); dest += pitch; src += srcpitch; } } GrowUpdateRegion(vnc,&trec); SDL_UnlockSurface(vnc->framebuffer); SDL_UnlockMutex(vnc->mutex); }
int read_raw(tSDL_vnc * vnc, tSDL_vnc_rect rect) { SDL_Rect trec; vnc_to_sdl_rect(&rect, &trec); SDL_LockMutex(vnc->mutex); SDL_LockSurface(vnc->framebuffer); uint32_t pitch = vnc->framebuffer->pitch/4; uint32_t * dest = (uint32_t *)vnc->framebuffer->pixels + (rect.y * pitch) + rect.x; uint32_t len = rect.width * rect.height * 4; DBMESSAGE("Reading %ld bytes straight into buffer", len); CHECKED_READ(vnc, dest, len, "framebuffer"); GrowUpdateRegion(vnc,&trec); SDL_UnlockSurface(vnc->framebuffer); SDL_UnlockMutex(vnc->mutex); return 1; }
int HandleServerMessage(tSDL_vnc *vnc) { int i, num_pixels, num_rectangles, num_subrectangles, hx, hy, bx, by, cx, cy, rowindex, bitindex, byteindex; int result, bytes_to_read, bytes_read; tSDL_vnc_serverMessage serverMessage; tSDL_vnc_serverUpdate serverUpdate; tSDL_vnc_serverRectangle serverRectangle; tSDL_vnc_serverColormap serverColormap; tSDL_vnc_serverText serverText; tSDL_vnc_serverCopyrect serverCopyrect; tSDL_vnc_serverRRE serverRRE; tSDL_vnc_serverRREdata serverRREdata; tSDL_vnc_serverCoRRE serverCoRRE; tSDL_vnc_serverCoRREdata serverCoRREdata; tSDL_vnc_serverHextile serverHextile; tSDL_vnc_serverHextileBg serverHextileBg; tSDL_vnc_serverHextileFg serverHextileFg; tSDL_vnc_serverHextileSubrects serverHextileSubrects; tSDL_vnc_serverHextileColored serverHextileColored; tSDL_vnc_serverHextileRect serverHextileRect; unsigned char *target; unsigned int *uitarget; unsigned char *cursormask; SDL_Rect trec, srec; DBMESSAGE ("HandleServerMessage\n"); /* Read message type */ result = Recv(vnc->socket,&serverMessage,1,0); if (result==1) { switch (serverMessage.messagetype) { case 0: DBMESSAGE ("Message: update\n"); result = Recv(vnc->socket,&serverUpdate,3,0); if (result==3) { /* ??? Protocol sais U16, TightVNC server sends U8 */ serverUpdate.rectangles=serverUpdate.rectangles & 0x00ff; DBMESSAGE ("Number of rectangles: %u (%04x)\n",serverUpdate.rectangles,serverUpdate.rectangles); num_rectangles=0; while (num_rectangles<serverUpdate.rectangles) { num_rectangles++; result = Recv(vnc->socket,&serverRectangle,12,0); if (result==12) { serverRectangle.x=swap_16(serverRectangle.x); serverRectangle.y=swap_16(serverRectangle.y); serverRectangle.width=swap_16(serverRectangle.width); serverRectangle.height=swap_16(serverRectangle.height); serverRectangle.encoding=swap_32(serverRectangle.encoding); // DBMESSAGE ("Rectangle %i of %i: @ %u,%u size %u,%u encoding %u\n",num_rectangles,serverUpdate.rectangles,serverRectangle.x,serverRectangle.y,serverRectangle.width,serverRectangle.height,serverRectangle.encoding); /* Sanity check values */ if (serverRectangle.x>vnc->serverFormat.width) { DBMESSAGE("Bad rectangle: x=%u setting to 0\n",serverRectangle.x); serverRectangle.x=0; } if (serverRectangle.y>vnc->serverFormat.height) { DBMESSAGE("Bad rectangle: y=%u setting to 0\n",serverRectangle.y); serverRectangle.y=0; } if ((serverRectangle.width<=0) || (serverRectangle.width>vnc->serverFormat.width)) { DBMESSAGE("Bad rectangle: width=%u setting to 1\n",serverRectangle.width); serverRectangle.width=1; } if ((serverRectangle.height<=0) || (serverRectangle.height>vnc->serverFormat.height)) { DBMESSAGE("Bad rectangle: height=%u setting to 1\n",serverRectangle.height); serverRectangle.height=1; } /* Do we have a scratchbuffer */ if (vnc->scratchbuffer) { /* Check size */ if ( (!(vnc->scratchbuffer->w == serverRectangle.width)) || (!(vnc->scratchbuffer->h == serverRectangle.height)) ) { /* Clean out existing scratchbuffer */ SDL_FreeSurface(vnc->scratchbuffer); vnc->scratchbuffer=NULL; DBMESSAGE ("Deleted existing scratchbuffer.\n"); } } if (!(vnc->scratchbuffer)) { /* Create new scratchbuffer */ vnc->scratchbuffer = SDL_CreateRGBSurface(SDL_SWSURFACE,serverRectangle.width,serverRectangle.height,32, vnc->rmask,vnc->gmask,vnc->bmask,0); if (vnc->scratchbuffer) { SDL_SetAlpha(vnc->scratchbuffer,0,0); DBMESSAGE ("Created new scratchbuffer.\n"); } else { DBERROR ("Error creating scratchbuffer.\n"); return 0; } } /* Rectangle Data */ switch (serverRectangle.encoding) { case 0: DBMESSAGE ("RAW encoding.\n"); bytes_to_read = serverRectangle.width*serverRectangle.height*4; result = Recv(vnc->socket,(unsigned char *)vnc->scratchbuffer->pixels,bytes_to_read,0); if (result==bytes_to_read) { DBMESSAGE ("Blitting %i bytes of raw pixel data.\n",bytes_to_read); trec.x=serverRectangle.x; trec.y=serverRectangle.y; trec.w=serverRectangle.width; trec.h=serverRectangle.height; SDL_LockMutex(vnc->mutex); SDL_BlitSurface(vnc->scratchbuffer, NULL, vnc->framebuffer, &trec); GrowUpdateRegion(vnc,&trec); SDL_UnlockMutex(vnc->mutex); DBMESSAGE ("Blitted raw pixel data.\n"); } else { DBERROR ("Error on pixel data. Got %i of %i bytes.\n",result,bytes_to_read); return 0; } break; case 1: DBMESSAGE ("CopyRect encoding.\n"); result = Recv(vnc->socket,&serverCopyrect,4,0); if (result==4) { serverCopyrect.x=swap_16(serverCopyrect.x); serverCopyrect.y=swap_16(serverCopyrect.y); // DBMESSAGE ("Copyrect from %u,%u\n",serverCopyrect.x,serverCopyrect.y); // srec.x=serverCopyrect.x; srec.y=serverCopyrect.y; srec.w=serverRectangle.width; srec.h=serverRectangle.height; trec.x=serverRectangle.x; trec.y=serverRectangle.y; trec.w=serverRectangle.width; trec.h=serverRectangle.height; SDL_LockMutex(vnc->mutex); SDL_BlitSurface(vnc->framebuffer, &srec, vnc->scratchbuffer, NULL); SDL_BlitSurface(vnc->scratchbuffer, NULL, vnc->framebuffer, &trec); GrowUpdateRegion(vnc,&trec); SDL_UnlockMutex(vnc->mutex); DBMESSAGE ("Blitted copyrect pixels.\n"); } else { DBERROR ("Error on copyrect data. Got %i of %i bytes.\n",result,4); return 0; } break; case 2: DBMESSAGE ("RRE encoding.\n"); result = Recv(vnc->socket,&serverRRE,8,0); if (result==8) { serverRRE.number=swap_32(serverRRE.number); // DBMESSAGE ("RRE of %u rectangles. Background color 0x%06x\n",serverRRE.number,serverRRE.background); SDL_FillRect(vnc->scratchbuffer, NULL, serverRRE.background); /* Draw subrectangles */ num_subrectangles=0; while (num_subrectangles<serverRRE.number) { num_subrectangles++; result = Recv(vnc->socket,&serverRREdata,12,0); if (result==12) { serverRREdata.x=swap_16(serverRREdata.x); serverRREdata.y=swap_16(serverRREdata.y); serverRREdata.width=swap_16(serverRREdata.width); serverRREdata.height=swap_16(serverRREdata.height); srec.x=serverRREdata.x; srec.y=serverRREdata.y; srec.w=serverRREdata.width; srec.h=serverRREdata.height; SDL_FillRect(vnc->scratchbuffer,&srec,serverRREdata.color); } else { DBERROR ("Error on RRE data. Got %i of %i bytes.\n",result,12); return 0; } } DBMESSAGE ("Drawn %i subrectangles.\n", num_subrectangles); trec.x=serverRectangle.x; trec.y=serverRectangle.y; trec.w=serverRectangle.width; trec.h=serverRectangle.height; SDL_LockMutex(vnc->mutex); SDL_BlitSurface(vnc->scratchbuffer, NULL, vnc->framebuffer, &trec); GrowUpdateRegion(vnc,&trec); SDL_UnlockMutex(vnc->mutex); DBMESSAGE ("Blitted RRE pixels.\n"); } else { DBERROR ("Error on RRE header. Got %i of %i bytes.\n",result,8); return 0; } break; case 4: DBMESSAGE ("CoRRE encoding.\n"); result = Recv(vnc->socket,&serverCoRRE,8,0); if (result==8) { serverCoRRE.number=swap_32(serverCoRRE.number); // DBMESSAGE ("CoRRE of %u rectangles. Background color 0x%06x\n",serverCoRRE.number,serverCoRRE.background); SDL_FillRect(vnc->scratchbuffer, NULL, serverCoRRE.background); /* Draw subrectangles */ num_subrectangles=0; while (num_subrectangles<serverCoRRE.number) { num_subrectangles++; result = Recv(vnc->socket,&serverCoRREdata,8,0); if (result==8) { srec.x=serverCoRREdata.x; srec.y=serverCoRREdata.y; srec.w=serverCoRREdata.width; srec.h=serverCoRREdata.height; SDL_FillRect(vnc->scratchbuffer,&srec,serverCoRREdata.color); } else { DBERROR ("Error on CoRRE data. Got %i of %i bytes.\n",result,8); return 0; } } DBMESSAGE ("Drawn %i subrectangles.\n", num_subrectangles); trec.x=serverRectangle.x; trec.y=serverRectangle.y; trec.w=serverRectangle.width; trec.h=serverRectangle.height; SDL_LockMutex(vnc->mutex); SDL_BlitSurface(vnc->scratchbuffer, NULL, vnc->framebuffer, &trec); GrowUpdateRegion(vnc,&trec); SDL_UnlockMutex(vnc->mutex); DBMESSAGE ("Blitted CoRRE pixels.\n"); } else { DBERROR ("Error on CoRRE header. Got %i of %i bytes.\n",result,8); return 0; } break; case 5: DBMESSAGE ("Hextile encoding.\n"); // if (!(vnc->tilebuffer)) { /* Create new tilebuffer */ vnc->tilebuffer = SDL_CreateRGBSurface(SDL_SWSURFACE,16,16,32, vnc->rmask,vnc->gmask,vnc->bmask,0); if (vnc->tilebuffer) { SDL_SetAlpha(vnc->tilebuffer,0,0); DBMESSAGE ("Created new tilebuffer.\n"); } else { DBERROR ("Error creating tilebuffer.\n"); return 0; } } // /* Iterate over all tiles */ // row loop for (hy=0; hy<serverRectangle.height; hy += 16) { /* Determine height of tile */ if ((hy+16)>serverRectangle.height) { by=serverRectangle.height % 16; } else { by=16; } // column loop for (hx=0; hx<serverRectangle.width; hx += 16) { /* Determine width of tile */ if ((hx+16)>serverRectangle.width) { bx=serverRectangle.width % 16; } else { bx=16; } result = Recv(vnc->socket,&serverHextile,1,0); if (result==1) { if (serverHextile.mode & 1) { /* Read raw data for tile in lines */ bytes_to_read = bx*by*4; if ((bx==16) && (by==16)) { // complete tile result = Recv(vnc->socket,(unsigned char *)vnc->tilebuffer->pixels,bytes_to_read,0); } else { // partial tile result = 0; target=(unsigned char *)vnc->tilebuffer->pixels; rowindex=by; while (rowindex) { result += Recv(vnc->socket,target,bx*4,0); target += 16*4; rowindex--; } } if (result==bytes_to_read) { trec.x=hx; trec.y=hy; trec.w=16; trec.h=16; SDL_BlitSurface(vnc->tilebuffer, NULL, vnc->scratchbuffer, &trec); } else { DBERROR ("Error on pixel data. Got %i of %i bytes.\n",result,bytes_to_read); return 0; } } else { /* no raw data */ if (serverHextile.mode & 2) { /* Read background */ result = Recv(vnc->socket,&serverHextileBg,4,0); if (result==4) { /* All OK */ } else { DBERROR ("Error on Hextile background. Got %i of %i bytes.\n",result,4); return 0; } } SDL_FillRect(vnc->tilebuffer,NULL,serverHextileBg.color); if (serverHextile.mode & 4) { /* Read foreground */ result = Recv(vnc->socket,&serverHextileFg,4,0); if (result==4) { /* All OK */ } else { DBERROR ("Error on Hextile foreground. Got %i of %i bytes.\n",result,4); return 0; } } if (serverHextile.mode & 8) { result = Recv(vnc->socket,&serverHextileSubrects,1,0); if (result==1) { /* All OK */ } else { DBERROR ("Error on Hextile subrects. Got %i of %i bytes.\n",result,1); return 0; } /* Read subrects */ num_subrectangles=0; while (num_subrectangles<serverHextileSubrects.number) { num_subrectangles++; // /* Check color mode */ if (serverHextile.mode & 16) { /* Colored subrect */ result = Recv(vnc->socket,&serverHextileColored,6,0); if (result==6) { /* Render colored subrect */ srec.x=(serverHextileColored.xy >> 4) & 0x0f; srec.y=serverHextileColored.xy & 0x0f; srec.w=((serverHextileColored.wh >> 4) & 0x0f)+1; srec.h=(serverHextileColored.wh & 0x0f)+1; SDL_FillRect(vnc->tilebuffer,&srec,serverHextileColored.color); } else { DBERROR ("Error on Hextile color subrect data. Got %i of %i bytes.\n",result,6); return 0; } } else { /* Non-colored Subrect */ result = Recv(vnc->socket,&serverHextileRect,2,0); if (result==2) { /* Render colored subrect */ srec.x=(serverHextileRect.xy >> 4) & 0x0f; srec.y=serverHextileRect.xy & 0x0f; srec.w=((serverHextileRect.wh >> 4) & 0x0f)+1; srec.h=(serverHextileRect.wh & 0x0f)+1; SDL_FillRect(vnc->tilebuffer,&srec,serverHextileFg.color); } else { DBERROR ("Error on Hextile subrect data. Got %i of %i bytes.\n",result,2); return 0; } } // color mode check } // subrect loop // } // have subrects /* Draw tile */ trec.x=hx; trec.y=hy; trec.w=16; trec.h=16; SDL_BlitSurface(vnc->tilebuffer, NULL, vnc->scratchbuffer, &trec); } // raw data check } else {