static int handleHextile(tSDL_vnc *vnc) { 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; } } return 1; }
static int read_security_type(tSDL_vnc *vnc) { if (vnc->versionMinor < 7) { // Read security type (simple) CHECKED_READ(vnc, vnc->buffer, 4, "security type"); vnc->security_type=vnc->buffer[3]; DBMESSAGE("Security type (read): %i\n", vnc->security_type); return 1; } // Addition for RFB 003 008 CHECKED_READ(vnc, vnc->buffer, 1, "security type"); // Security Type List! Receive number of supported Security Types int nSecTypes = vnc->buffer[0]; if (nSecTypes == 0) { DBERROR("Server offered an empty list of security types.\n"); return 0; } // Receive Security Type List (Buffer overflow possible!) int result = Recv(vnc->socket,vnc->buffer,nSecTypes,0); // Find supported one... vnc->security_type = 0; int i; for (i = 0; i < result; i++) { vnc->security_type = vnc->buffer[i]; // Break if supported type (currently 1 or 2) found if ((vnc->security_type == 1) || (vnc->security_type == 2)) break; } // Select it DBMESSAGE("Security type (select): %i\n", vnc->security_type); vnc->buffer[0] = vnc->security_type; result = send(vnc->socket,vnc->buffer,1,0); if (result != 1) { DBERROR("Write error on security type selection.\n"); return 0; } return 1; }
/* FIXME: Is this valid when we never request a non-truecolor display? */ static int HandleServerMessage_colormap(tSDL_vnc * vnc) { tSDL_vnc_serverColormap serverColormap; DBMESSAGE("Message: colormap\n"); // Read data, but ignore it CHECKED_READ(vnc, &serverColormap, 5, "server colormap"); serverColormap.first=swap_16(serverColormap.first); serverColormap.number=swap_16(serverColormap.number); DBMESSAGE("Server colormap first color: %u\n",serverColormap.first); DBMESSAGE("Server colormap number: %u\n",serverColormap.number); while (serverColormap.number>0) { CHECKED_READ(vnc, &vnc->buffer, 6, "server colormap color"); DBMESSAGE("Got color %u.\n",serverColormap.first); serverColormap.first++; serverColormap.number--; } return 1; }
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; }
static int WaitForMessage(tSDL_vnc *vnc, unsigned int usecs) { fd_set fds; struct timeval timeout; int result; timeout.tv_sec=0; timeout.tv_usec=usecs; FD_ZERO(&fds); FD_SET(vnc->socket,&fds); result=select(vnc->socket+1, &fds, NULL, NULL, &timeout); #ifdef DEBUG if (result<0) { DBMESSAGE("Waiting for message failed: %d (%s)\n",errno,strerror(errno)); } #endif return result; }
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 {