void rfbUpdateClient(rfbClientPtr cl) { struct timeval tv; if (cl->sock >= 0 && !cl->onHold && FB_UPDATE_PENDING(cl) && !sraRgnEmpty(cl->requestedRegion)) { if(cl->screen->rfbDeferUpdateTime == 0) { rfbSendFramebufferUpdate(cl,cl->modifiedRegion); } else if(cl->startDeferring.tv_usec == 0) { gettimeofday(&cl->startDeferring,NULL); if(cl->startDeferring.tv_usec == 0) cl->startDeferring.tv_usec++; } else { gettimeofday(&tv,NULL); if(tv.tv_sec < cl->startDeferring.tv_sec /* at midnight */ || ((tv.tv_sec-cl->startDeferring.tv_sec)*1000 +(tv.tv_usec-cl->startDeferring.tv_usec)/1000) > cl->screen->rfbDeferUpdateTime) { cl->startDeferring.tv_usec = 0; rfbSendFramebufferUpdate(cl,cl->modifiedRegion); } } } }
rfbBool rfbUpdateClient(rfbClientPtr cl) { struct timeval tv; rfbBool result=FALSE; rfbScreenInfoPtr screen = cl->screen; if (cl->sock >= 0 && !cl->onHold && FB_UPDATE_PENDING(cl) && !sraRgnEmpty(cl->requestedRegion)) { result=TRUE; if(screen->deferUpdateTime == 0) { rfbSendFramebufferUpdate(cl,cl->modifiedRegion); } else if(cl->startDeferring.tv_usec == 0) { gettimeofday(&cl->startDeferring,NULL); if(cl->startDeferring.tv_usec == 0) cl->startDeferring.tv_usec++; } else { gettimeofday(&tv,NULL); if(tv.tv_sec < cl->startDeferring.tv_sec /* at midnight */ || ((tv.tv_sec-cl->startDeferring.tv_sec)*1000 +(tv.tv_usec-cl->startDeferring.tv_usec)/1000) > screen->deferUpdateTime) { cl->startDeferring.tv_usec = 0; rfbSendFramebufferUpdate(cl,cl->modifiedRegion); } } } if (!cl->viewOnly && cl->lastPtrX >= 0) { if(cl->startPtrDeferring.tv_usec == 0) { gettimeofday(&cl->startPtrDeferring,NULL); if(cl->startPtrDeferring.tv_usec == 0) cl->startPtrDeferring.tv_usec++; } else { struct timeval tv; gettimeofday(&tv,NULL); if(tv.tv_sec < cl->startPtrDeferring.tv_sec /* at midnight */ || ((tv.tv_sec-cl->startPtrDeferring.tv_sec)*1000 +(tv.tv_usec-cl->startPtrDeferring.tv_usec)/1000) > cl->screen->deferPtrUpdateTime) { cl->startPtrDeferring.tv_usec = 0; cl->screen->ptrAddEvent(cl->lastPtrButtons, cl->lastPtrX, cl->lastPtrY, cl); cl->lastPtrX = -1; } } } return result; }
void rfbProcessEvents(rfbScreenInfoPtr rfbScreen,long usec) { rfbClientIteratorPtr i; rfbClientPtr cl,clPrev; struct timeval tv; if(usec<0) usec=rfbScreen->rfbDeferUpdateTime*1000; rfbCheckFds(rfbScreen,usec); httpCheckFds(rfbScreen); #ifdef CORBA corbaCheckFds(rfbScreen); #endif i = rfbGetClientIterator(rfbScreen); cl=rfbClientIteratorNext(i); while(cl) { if(cl->sock>=0 && (!cl->onHold) && FB_UPDATE_PENDING(cl)) { if(cl->screen->rfbDeferUpdateTime == 0) { rfbSendFramebufferUpdate(cl,cl->modifiedRegion); } else if(cl->startDeferring.tv_usec == 0) { gettimeofday(&cl->startDeferring,NULL); if(cl->startDeferring.tv_usec == 0) cl->startDeferring.tv_usec++; } else { gettimeofday(&tv,NULL); if(tv.tv_sec < cl->startDeferring.tv_sec /* at midnight */ || ((tv.tv_sec-cl->startDeferring.tv_sec)*1000 +(tv.tv_usec-cl->startDeferring.tv_usec)/1000) > cl->screen->rfbDeferUpdateTime) { cl->startDeferring.tv_usec = 0; rfbSendFramebufferUpdate(cl,cl->modifiedRegion); } } } clPrev=cl; cl=rfbClientIteratorNext(i); if(clPrev->sock==-1) rfbClientConnectionGone(clPrev); } rfbReleaseClientIterator(i); }
static void * clientOutput(void *data) { rfbClientPtr cl = (rfbClientPtr)data; Bool haveUpdate; sraRegion* updateRegion; while (1) { haveUpdate = false; while (!haveUpdate) { if (cl->sock == -1) { /* Client has disconnected. */ return NULL; } LOCK(cl->updateMutex); haveUpdate = FB_UPDATE_PENDING(cl); if(!haveUpdate) { updateRegion = sraRgnCreateRgn(cl->modifiedRegion); haveUpdate = sraRgnAnd(updateRegion,cl->requestedRegion); sraRgnDestroy(updateRegion); } UNLOCK(cl->updateMutex); if (!haveUpdate) { TIMEDWAIT(cl->updateCond, cl->updateMutex, PING_MS); UNLOCK(cl->updateMutex); /* we really needn't lock now. */ if (!haveUpdate) rfbSendPing(cl); } } /* OK, now, to save bandwidth, wait a little while for more updates to come along. */ usleep(cl->screen->rfbDeferUpdateTime * 1000); /* Now, get the region we're going to update, and remove it from cl->modifiedRegion _before_ we send the update. That way, if anything that overlaps the region we're sending is updated, we'll be sure to do another update later. */ LOCK(cl->updateMutex); updateRegion = sraRgnCreateRgn(cl->modifiedRegion); UNLOCK(cl->updateMutex); /* Now actually send the update. */ rfbIncrClientRef(cl); rfbSendFramebufferUpdate(cl, updateRegion); rfbDecrClientRef(cl); sraRgnDestroy(updateRegion); } return NULL; }
static void * clientOutput(void *data) { rfbClientPtr cl = (rfbClientPtr)data; rfbBool haveUpdate; sraRegion* updateRegion; while (1) { haveUpdate = false; while (!haveUpdate) { if (cl->sock == -1) { /* Client has disconnected. */ return NULL; } if (cl->state != RFB_NORMAL || cl->onHold) { /* just sleep until things get normal */ usleep(cl->screen->deferUpdateTime * 1000); continue; } LOCK(cl->updateMutex); if (sraRgnEmpty(cl->requestedRegion)) { ; /* always require a FB Update Request (otherwise can crash.) */ } else { haveUpdate = FB_UPDATE_PENDING(cl); if(!haveUpdate) { updateRegion = sraRgnCreateRgn(cl->modifiedRegion); haveUpdate = sraRgnAnd(updateRegion,cl->requestedRegion); sraRgnDestroy(updateRegion); } } if (!haveUpdate) { WAIT(cl->updateCond, cl->updateMutex); } UNLOCK(cl->updateMutex); } /* OK, now, to save bandwidth, wait a little while for more updates to come along. */ usleep(cl->screen->deferUpdateTime * 1000); /* Now, get the region we're going to update, and remove it from cl->modifiedRegion _before_ we send the update. That way, if anything that overlaps the region we're sending is updated, we'll be sure to do another update later. */ LOCK(cl->updateMutex); updateRegion = sraRgnCreateRgn(cl->modifiedRegion); UNLOCK(cl->updateMutex); /* Now actually send the update. */ rfbIncrClientRef(cl); LOCK(cl->sendMutex); rfbSendFramebufferUpdate(cl, updateRegion); UNLOCK(cl->sendMutex); rfbDecrClientRef(cl); sraRgnDestroy(updateRegion); } /* Not reached. */ return NULL; }
int VNCServer::Client::Run() { Log(">VNCServer::Client::Run [this:%p]\n",this); //Lock LOCK(cl->updateMutex); //Set new modified region cl->modifiedRegion = sraRgnCreateRect(0,0,cl->screen->width,cl->screen->height); //Until ended while (!wait.IsCanceled()) { Debug("-VNCServer::Client lopp [this:%p,state:%d,empty:%d]\n",this,cl->state,sraRgnEmpty(cl->requestedRegion)); //If connected, always require a FB Update Request (otherwise can crash.) if (cl->state == rfbClientRec::RFB_NORMAL && !sraRgnEmpty(cl->requestedRegion)) { //If reseted if (reset) { Log("-Reseting client\n"); //Reset message char msg[] = {16}; //Write it if (!Write(msg,sizeof(msg))) //WS closed break; //Clear reset flag reset = false; } /* //If the scren has been resized if (cl->newFBSizePending) { //Free region sraRgnDestroy(cl->modifiedRegion); //Set new modified region cl->modifiedRegion = sraRgnCreateRect(0,0,cl->screen->width,cl->screen->height); } */ //We need to update by default bool haveUpdate = true; /* Now, get the region we're going to update, and remove it from cl->modifiedRegion _before_ we send the update. That way, if anything that overlaps the region we're sending is updated, we'll be sure to do another update later. */ sraRegion* updateRegion = sraRgnCreateRgn(cl->modifiedRegion); //Check if we didn't already have a pending update if (!FB_UPDATE_PENDING(cl)) //Check it is inside requested region haveUpdate = !sraRgnEmpty(cl->modifiedRegion);//sraRgnAnd(updateRegion,cl->requestedRegion); //IF we are freezed if (freeze) //Don't send any change sraRgnMakeEmpty(updateRegion); //Clean modified region sraRgnMakeEmpty(cl->modifiedRegion); //Unlock region UNLOCK(cl->updateMutex); Debug("-VNCServer::Client update [this:%p,update:%d,mod:%d,req:%d]\n",this,haveUpdate,sraRgnEmpty(cl->modifiedRegion),sraRgnEmpty(cl->requestedRegion)); //If we have to update and not freezed if (haveUpdate) { Debug(">VNCServer::Client SendFramebufferUpdate [%p]\n",this); /* Now actually send the update. */ rfbIncrClientRef(cl); //LOCK(cl->sendMutex); rfbSendFramebufferUpdate(cl, updateRegion); //UNLOCK(cl->sendMutex); rfbDecrClientRef(cl); Debug("<VNCServer::Client SendFramebufferUpdate [%p]\n",this); } //Destroy region sraRgnDestroy(updateRegion); //Lock again LOCK(cl->updateMutex); } //Check if we have been cancelled if (wait.IsCanceled()) //Exit break; //Wait cond Debug("<VNCServer::Client going to sleep [this:%p]\n",this); WAIT(cl->updateCond,cl->updateMutex); Debug(">VNCServer::Client waked up from wait mutex[this:%p,isCanceled:%d]\n",this,wait.IsCanceled()); } //Unlock UNLOCK(cl->updateMutex); Log("<VNCServer::Client::Run [this:%p]\n",this); //OK return 0; }
rfbBool rfbProcessEvents(rfbScreenInfoPtr screen,long usec) { rfbClientIteratorPtr i; rfbClientPtr cl,clPrev; struct timeval tv; rfbBool result=FALSE; extern rfbClientIteratorPtr rfbGetClientIteratorWithClosed(rfbScreenInfoPtr rfbScreen); if(usec<0) usec=screen->deferUpdateTime*1000; rfbCheckFds(screen,usec); rfbHttpCheckFds(screen); i = rfbGetClientIteratorWithClosed(screen); cl=rfbClientIteratorHead(i); while(cl) { if (cl->sock >= 0 && !cl->onHold && FB_UPDATE_PENDING(cl) && !sraRgnEmpty(cl->requestedRegion)) { result=TRUE; if(screen->deferUpdateTime == 0) { rfbSendFramebufferUpdate(cl,cl->modifiedRegion); } else if(cl->startDeferring.tv_usec == 0) { gettimeofday(&cl->startDeferring,NULL); if(cl->startDeferring.tv_usec == 0) cl->startDeferring.tv_usec++; } else { gettimeofday(&tv,NULL); if(tv.tv_sec < cl->startDeferring.tv_sec /* at midnight */ || ((tv.tv_sec-cl->startDeferring.tv_sec)*1000 +(tv.tv_usec-cl->startDeferring.tv_usec)/1000) > screen->deferUpdateTime) { cl->startDeferring.tv_usec = 0; rfbSendFramebufferUpdate(cl,cl->modifiedRegion); } } } if (!cl->viewOnly && cl->lastPtrX >= 0) { if(cl->startPtrDeferring.tv_usec == 0) { gettimeofday(&cl->startPtrDeferring,NULL); if(cl->startPtrDeferring.tv_usec == 0) cl->startPtrDeferring.tv_usec++; } else { struct timeval tv; gettimeofday(&tv,NULL); if(tv.tv_sec < cl->startPtrDeferring.tv_sec /* at midnight */ || ((tv.tv_sec-cl->startPtrDeferring.tv_sec)*1000 +(tv.tv_usec-cl->startPtrDeferring.tv_usec)/1000) > cl->screen->deferPtrUpdateTime) { cl->startPtrDeferring.tv_usec = 0; cl->screen->ptrAddEvent(cl->lastPtrButtons, cl->lastPtrX, cl->lastPtrY, cl); cl->lastPtrX = -1; } } } clPrev=cl; cl=rfbClientIteratorNext(i); if(clPrev->sock==-1) { rfbClientConnectionGone(clPrev); result=TRUE; } } rfbReleaseClientIterator(i); return result; }
void rfbScheduleCopyRegion(rfbScreenInfoPtr rfbScreen,sraRegionPtr copyRegion,int dx,int dy) { rfbClientIteratorPtr iterator; rfbClientPtr cl; iterator=rfbGetClientIterator(rfbScreen); while((cl=rfbClientIteratorNext(iterator))) { LOCK(cl->updateMutex); if(cl->useCopyRect) { sraRegionPtr modifiedRegionBackup; if(!sraRgnEmpty(cl->copyRegion)) { if(cl->copyDX!=dx || cl->copyDY!=dy) { /* if a copyRegion was not yet executed, treat it as a * modifiedRegion. The idea: in this case it could be * source of the new copyRect or modified anyway. */ sraRgnOr(cl->modifiedRegion,cl->copyRegion); sraRgnMakeEmpty(cl->copyRegion); } else { /* we have to set the intersection of the source of the copy * and the old copy to modified. */ modifiedRegionBackup=sraRgnCreateRgn(copyRegion); sraRgnOffset(modifiedRegionBackup,-dx,-dy); sraRgnAnd(modifiedRegionBackup,cl->copyRegion); sraRgnOr(cl->modifiedRegion,modifiedRegionBackup); sraRgnDestroy(modifiedRegionBackup); } } sraRgnOr(cl->copyRegion,copyRegion); cl->copyDX = dx; cl->copyDY = dy; /* if there were modified regions, which are now copied, * mark them as modified, because the source of these can be overlapped * either by new modified or now copied regions. */ modifiedRegionBackup=sraRgnCreateRgn(cl->modifiedRegion); sraRgnOffset(modifiedRegionBackup,dx,dy); sraRgnAnd(modifiedRegionBackup,cl->copyRegion); sraRgnOr(cl->modifiedRegion,modifiedRegionBackup); sraRgnDestroy(modifiedRegionBackup); #if 0 /* TODO: is this needed? Or does it mess up deferring? */ /* while(!sraRgnEmpty(cl->copyRegion)) */ { { sraRegionPtr updateRegion = sraRgnCreateRgn(cl->modifiedRegion); sraRgnOr(updateRegion,cl->copyRegion); UNLOCK(cl->updateMutex); rfbSendFramebufferUpdate(cl,updateRegion); sraRgnDestroy(updateRegion); continue; } } #endif } else { sraRgnOr(cl->modifiedRegion,copyRegion); } UNLOCK(cl->updateMutex); } rfbReleaseClientIterator(iterator); }