void rfbScreenCleanup(rfbScreenInfoPtr rfbScreen) { rfbClientIteratorPtr i=rfbGetClientIterator(rfbScreen); rfbClientPtr cl,cl1=rfbClientIteratorNext(i); while(cl1) { cl=rfbClientIteratorNext(i); rfbClientConnectionGone(cl1); cl1=cl; } rfbReleaseClientIterator(i); rfbAuthCleanupScreen(rfbScreen); /* TODO: hang up on all clients and free all reserved memory */ #define FREE_IF(x) if(rfbScreen->x) free(rfbScreen->x) FREE_IF(colourMap.data.bytes); FREE_IF(underCursorBuffer); if(rfbScreen->cursor) rfbFreeCursor(rfbScreen->cursor); if(rfbScreen->desktopName) free(rfbScreen->desktopName); free(rfbScreen); #ifdef VINO_HAVE_JPEG rfbTightCleanup(); #endif }
static void _ecore_evas_vnc_server_update_clients(rfbScreenInfoPtr vnc_screen) { rfbClientIteratorPtr itr; rfbClientRec *client; itr = rfbGetClientIterator(vnc_screen); //No clients. if (!itr) return; while ((client = rfbClientIteratorNext(itr))) { rfbBool r; r = rfbUpdateClient(client); if (!r) { Ecore_Evas_Vnc_Server_Client_Data *cdata = client->clientData; WRN("Could not update the VNC client on seat '%s'\n", evas_device_name_get(cdata->seat)); } //Client disconnected if (client->sock == -1) rfbClientConnectionGone(client); } rfbReleaseClientIterator(itr); }
rfbBool rfbProcessEvents(rfbScreenInfoPtr screen,long usec) { rfbClientIteratorPtr i; rfbClientPtr cl,clPrev; 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) { result = rfbUpdateClient(cl); clPrev=cl; cl=rfbClientIteratorNext(i); if(clPrev->sock==-1) { rfbClientConnectionGone(clPrev); result=TRUE; } } rfbReleaseClientIterator(i); return result; }
//! this is called before every frame, used for polling for RFB messages void VncServer::preFrame() { const int wait_msec=1; if (m_delay) { usleep(m_delay); } if (m_numClients == 0) { for (size_t i=0; i<m_clientList.size(); ++i) { if (rfbReverseConnection(m_screen, const_cast<char *>(m_clientList[i].host.c_str()), m_clientList[i].port)) { break; } } } rfbCheckFds(m_screen, wait_msec*1000); rfbHttpCheckFds(m_screen); rfbClientIteratorPtr i = rfbGetClientIterator(m_screen); while (rfbClientPtr cl = rfbClientIteratorNext(i)) { if (rfbUpdateClient(cl)) { } } rfbReleaseClientIterator(i); }
void VNCEnumUsers(HVNC hVNC,CLIENTSENUMPROC *lpEnumProc) { HVNC_HANDLE *lpHandle=VNCGetHandleInformation(hVNC); if ((!lpEnumProc) || (!lpHandle) || (!lpHandle->lpServer)) return; PHVNC lpServer=lpHandle->lpServer; if (lpServer->EventsInfo.dwClients) { HVNC_CLIENT_INFO ClientInfo={0}; ClientInfo.hVNC=hVNC; rfbClientIteratorPtr i=rfbGetClientIteratorWithClosed(lpServer->rfbScreen); rfbClientPtr cl=rfbClientIteratorHead(i); while (cl) { HVNC_SHORT_CLIENT_INFO *lpClientInfo=(HVNC_SHORT_CLIENT_INFO *)cl->clientData; memcpy(&ClientInfo.saClient,&lpClientInfo->saClient,sizeof(ClientInfo.saClient)); memcpy(&ClientInfo.piPassword,&lpClientInfo->piPassword,sizeof(ClientInfo.piPassword)); if (!lpEnumProc(&ClientInfo)) break; cl=rfbClientIteratorNext(i); } rfbReleaseClientIterator(i); } return; }
void VNCDisconnectUser(HVNC hVNC,char *lpPassword,in_addr dwAddr) { HVNC_HANDLE *lpHandle=VNCGetHandleInformation(hVNC); if ((!lpHandle) || (!lpHandle->lpServer)) return; PHVNC lpServer=lpHandle->lpServer; if (lpServer->EventsInfo.dwClients) { rfbClientIteratorPtr i=rfbGetClientIteratorWithClosed(lpServer->rfbScreen); rfbClientPtr cl=rfbClientIteratorHead(i); while (cl) { rfbClientPtr clPrev=cl; cl=rfbClientIteratorNext(i); HVNC_SHORT_CLIENT_INFO *lpClientInfo=(HVNC_SHORT_CLIENT_INFO *)clPrev->clientData; if ((lpClientInfo->saClient.sin_addr.s_addr == dwAddr.s_addr) && ((!lpPassword) || (!lstrcmpA(lpClientInfo->piPassword.szPassword,lpPassword)))) { rfbClientConnectionGone(clPrev); break; } } rfbReleaseClientIterator(i); } return; }
void rfbDefaultPtrAddEvent(int buttonMask, int x, int y, rfbClientPtr cl) { rfbClientIteratorPtr iterator; rfbClientPtr other_client; rfbScreenInfoPtr s = cl->screen; if (x != s->cursorX || y != s->cursorY) { LOCK(s->cursorMutex); s->cursorX = x; s->cursorY = y; UNLOCK(s->cursorMutex); /* The cursor was moved by this client, so don't send CursorPos. */ if (cl->enableCursorPosUpdates) cl->cursorWasMoved = FALSE; /* But inform all remaining clients about this cursor movement. */ iterator = rfbGetClientIterator(s); while ((other_client = rfbClientIteratorNext(iterator)) != NULL) { if (other_client != cl && other_client->enableCursorPosUpdates) { other_client->cursorWasMoved = TRUE; } } rfbReleaseClientIterator(iterator); } }
static void FUNCTION(rfbScreenInfoPtr screen) { OUT_T* buffer = (OUT_T*)screen->frameBuffer; int i, j, w = screen->width, h = screen->height; OUT_T* newBuffer = (OUT_T*)malloc(w * h * sizeof(OUT_T)); for (j = 0; j < h; j++) for (i = 0; i < w; i++) newBuffer[FUNC(i, j)] = buffer[i + j * w]; memcpy(buffer, newBuffer, w * h * sizeof(OUT_T)); free(newBuffer); #ifdef SWAPDIMENSIONS screen->width = h; screen->paddedWidthInBytes = h * OUT / 8; screen->height = w; { rfbClientIteratorPtr iterator; rfbClientPtr cl; iterator = rfbGetClientIterator(screen); while ((cl = rfbClientIteratorNext(iterator)) != NULL) cl->newFBSizePending = 1; } #endif rfbMarkRectAsModified(screen, 0, 0, screen->width, screen->height); }
void rotate(int value) { L("rotate()\n"); if (value == -1 || ((value == 90 || value == 270) && (rotation == 0 || rotation == 180)) || ((value == 0 || value == 180) && (rotation == 90 || rotation == 270))) { int h = vncscr->height; int w = vncscr->width; vncscr->width = h; vncscr->paddedWidthInBytes = h * screenformat.bitsPerPixel / CHAR_BIT; vncscr->height = w; rfbClientIteratorPtr iterator; rfbClientPtr cl; iterator = rfbGetClientIterator(vncscr); while ((cl = rfbClientIteratorNext(iterator)) != NULL) cl->newFBSizePending = 1; } if (value == -1) { rotation += 90; rotation %= 360; } else { rotation = value; } rfbMarkRectAsModified(vncscr, 0, 0, vncscr->width, vncscr->height); }
void rfbScreenCleanup(rfbScreenInfoPtr rfbScreen) { rfbClientIteratorPtr i=rfbGetClientIterator(rfbScreen); rfbClientPtr cl,cl1=rfbClientIteratorNext(i); while(cl1) { cl=rfbClientIteratorNext(i); rfbClientConnectionGone(cl1); cl1=cl; } rfbReleaseClientIterator(i); /* TODO: hang up on all clients and free all reserved memory */ #define FREE_IF(x) if(rfbScreen->x) free(rfbScreen->x) FREE_IF(colourMap.data.bytes); FREE_IF(underCursorBuffer); TINI_MUTEX(rfbScreen->cursorMutex); free(rfbScreen); }
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); }
//! send generic application message to all connected clients void VncServer::broadcastApplicationMessage(int type, int length, const char *data) { rfbClientIteratorPtr it = rfbGetClientIterator(m_screen); while (rfbClientPtr cl = rfbClientIteratorNext(it)) { struct ClientData *cd = static_cast<ClientData *>(cl->clientData); if (cd && cd->supportsApplication) sendApplicationMessage(cl, type, length, data); } rfbReleaseClientIterator(it); }
static int get_latency(void) { rfbClientIteratorPtr iter; rfbClientPtr cl; int ilat, ilat_min = 1; /* 1 ms */ int ilat_max = 2000; /* 2 sec */ double slowest = -1.0, lat; static double save_lat = ((double) LATENCY0)/1000.0; int count = 0; if (!screen) { return 0; } iter = rfbGetClientIterator(screen); while( (cl = rfbClientIteratorNext(iter)) ) { ClientData *cd = (ClientData *) cl->clientData; if (! cd) { continue; } if (cl->state != RFB_NORMAL) { continue; } if (cd->latency == 0.0) { continue; } count++; lat = cd->latency; if (slowest == -1.0 || lat > slowest) { slowest = lat; } } rfbReleaseClientIterator(iter); if (! count) { return LATENCY0; } if (slowest == -1.0) { slowest = save_lat; } else { save_lat = slowest; } ilat = (int) (slowest * 1000.0); if (ilat < ilat_min) { ilat = ilat_min; } if (ilat > ilat_max) { ilat = ilat_max; } return ilat; }
void rfbSetClientColourMaps(rfbScreenInfoPtr rfbScreen, int firstColour, int nColours) { rfbClientIteratorPtr i; rfbClientPtr cl; i = rfbGetClientIterator(rfbScreen); while((cl = rfbClientIteratorNext(i))) rfbSetClientColourMap(cl, firstColour, nColours); rfbReleaseClientIterator(i); }
void rfbScreenCleanup(rfbScreenInfoPtr screen) { rfbClientIteratorPtr i=rfbGetClientIterator(screen); rfbClientPtr cl,cl1=rfbClientIteratorNext(i); while(cl1) { cl=rfbClientIteratorNext(i); rfbClientConnectionGone(cl1); cl1=cl; } rfbReleaseClientIterator(i); #define FREE_IF(x) if(screen->x) free(screen->x) FREE_IF(colourMap.data.bytes); FREE_IF(underCursorBuffer); TINI_MUTEX(screen->cursorMutex); if(screen->cursor && screen->cursor->cleanup) rfbFreeCursor(screen->cursor); rfbRRECleanup(screen); rfbCoRRECleanup(screen); rfbUltraCleanup(screen); #ifdef LIBVNCSERVER_HAVE_LIBZ rfbZlibCleanup(screen); #ifdef LIBVNCSERVER_HAVE_LIBJPEG rfbTightCleanup(screen); #endif /* free all 'scaled' versions of this screen */ while (screen->scaledScreenNext!=NULL) { rfbScreenInfoPtr ptr; ptr = screen->scaledScreenNext; screen->scaledScreenNext = ptr->scaledScreenNext; free(ptr->frameBuffer); free(ptr); } #endif free(screen); }
void ScreenToVnc::updateClientCursors(rfbScreenInfoPtr rfbScreen, bool emptyMouse) { rfbClientIteratorPtr iter; rfbClientPtr cl; iter = rfbGetClientIterator(rfbScreen); while( (cl = rfbClientIteratorNext(iter)) ) { cl->cursorWasChanged = true; } rfbReleaseClientIterator(iter); isEmptyMouse = emptyMouse; }
void rfbMarkRegionAsModified(rfbScreenInfoPtr rfbScreen,sraRegionPtr modRegion) { rfbClientIteratorPtr iterator; rfbClientPtr cl; iterator=rfbGetClientIterator(rfbScreen); while((cl=rfbClientIteratorNext(iterator))) { LOCK(cl->updateMutex); sraRgnOr(cl->modifiedRegion,modRegion); UNLOCK(cl->updateMutex); } rfbReleaseClientIterator(iterator); }
void rfbShutdownServer(rfbScreenInfoPtr screen,rfbBool disconnectClients) { if(disconnectClients) { rfbClientPtr cl; rfbClientIteratorPtr iter = rfbGetClientIterator(screen); while( (cl = rfbClientIteratorNext(iter)) ) if (cl->sock > -1) /* we don't care about maxfd here, because the server goes away */ rfbCloseClient(cl); rfbReleaseClientIterator(iter); } rfbShutdownSockets(screen); rfbHttpShutdownSockets(screen); }
void rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec) { int nfds; int n; fd_set fds; struct timeval tv; rfbClientIteratorPtr i; rfbClientPtr cl; if (!rfbScreen->inetdInitDone && rfbScreen->inetdSock != -1) { rfbNewClientConnection(rfbScreen,rfbScreen->inetdSock); rfbScreen->inetdInitDone = TRUE; } memcpy(&fds, &rfbScreen->allFds, sizeof(fd_set)); tv.tv_sec = 0; tv.tv_usec = usec; nfds = select(rfbScreen->maxFd + 1, &fds, NULL, NULL /* &fds */, &tv); if (nfds == 0) { return; } if (nfds < 0) { #ifdef WIN32 errno = WSAGetLastError(); #endif if (errno != EINTR) rfbLogPerror("rfbCheckFds: select"); return; } printf("DUMP: nfds = %d\n", nfds); for(n=0; n < rfbScreen->rfbListenSockTotal; n++) { if (rfbScreen->rfbListenSock[n] != -1 && FD_ISSET(rfbScreen->rfbListenSock[n], &fds)) { rfbProcessNewConnection(rfbScreen, rfbScreen->rfbListenSock[n]); FD_CLR(rfbScreen->rfbListenSock[n], &fds); if (--nfds == 0) return; } } i = rfbGetClientIterator(rfbScreen); while((cl = rfbClientIteratorNext(i))) { if (cl->onHold) continue; if (FD_ISSET(cl->sock, &fds) && FD_ISSET(cl->sock, &(rfbScreen->allFds))) rfbProcessClientMessage(cl); } rfbReleaseClientIterator(i); }
static void DisconnectUser(PHVNC lpServer,PASSWORD_ITEM *lpPassword) { if (lpServer->EventsInfo.dwClients) { rfbClientIteratorPtr i=rfbGetClientIteratorWithClosed(lpServer->rfbScreen); rfbClientPtr cl=rfbClientIteratorHead(i); while (cl) { rfbClientPtr clPrev=cl; cl=rfbClientIteratorNext(i); HVNC_SHORT_CLIENT_INFO *lpClientInfo=(HVNC_SHORT_CLIENT_INFO *)clPrev->clientData; if ((!lpPassword) || (!lstrcmpA(lpClientInfo->piPassword.szPassword,lpPassword->szPassword))) rfbClientConnectionGone(clPrev); } rfbReleaseClientIterator(i); } return; }
static void handle_xrandr_change(int new_x, int new_y) { rfbClientIteratorPtr iter; rfbClientPtr cl; RAWFB_RET_VOID /* assumes no X_LOCK */ /* sanity check xrandr_mode */ if (! xrandr_mode) { xrandr_mode = strdup("default"); } else if (! known_xrandr_mode(xrandr_mode)) { free(xrandr_mode); xrandr_mode = strdup("default"); } rfbLog("xrandr_mode: %s\n", xrandr_mode); if (!strcmp(xrandr_mode, "exit")) { close_all_clients(); rfbLog(" shutting down due to XRANDR event.\n"); clean_up_exit(0); } if (!strcmp(xrandr_mode, "newfbsize") && screen) { iter = rfbGetClientIterator(screen); while( (cl = rfbClientIteratorNext(iter)) ) { if (cl->useNewFBSize) { continue; } rfbLog(" closing client %s (no useNewFBSize" " support).\n", cl->host); rfbCloseClient(cl); rfbClientConnectionGone(cl); } rfbReleaseClientIterator(iter); } /* default, resize, and newfbsize create a new fb: */ rfbLog("check_xrandr_event: trying to create new framebuffer...\n"); if (new_x < wdpy_x || new_y < wdpy_y) { check_black_fb(); } do_new_fb(1); rfbLog("check_xrandr_event: fb WxH: %dx%d\n", wdpy_x, wdpy_y); }
void rfbNewFramebuffer(rfbScreenInfoPtr rfbScreen, char *framebuffer, int width, int height) { rfbClientIteratorPtr iterator; rfbClientPtr cl; if (width & 3) rfbErr("WARNING: New width (%d) is not a multiple of 4.\n", width); /* Update information in the rfbScreenInfo structure */ rfbScreen->width = width; rfbScreen->height = height; rfbScreen->frameBuffer = framebuffer; /* Adjust pointer position if necessary */ if (rfbScreen->cursorX >= width) rfbScreen->cursorX = width - 1; if (rfbScreen->cursorY >= height) rfbScreen->cursorY = height - 1; /* For each client: */ iterator = rfbGetClientIterator(rfbScreen); while ((cl = rfbClientIteratorNext(iterator)) != NULL) { /* Mark the screen contents as changed, and schedule sending NewFBSize message if supported by this client. */ LOCK(cl->updateMutex); sraRgnDestroy(cl->modifiedRegion); cl->modifiedRegion = sraRgnCreateRect(0, 0, width, height); sraRgnMakeEmpty(cl->copyRegion); cl->copyDX = 0; cl->copyDY = 0; if (cl->useNewFBSize) cl->newFBSizePending = TRUE; UNLOCK(cl->updateMutex); } rfbReleaseClientIterator(iterator); }
void VNCDisconnectAllUsers(HVNC hVNC) { HVNC_HANDLE *lpHandle=VNCGetHandleInformation(hVNC); if ((!lpHandle) || (!lpHandle->lpServer)) return; PHVNC lpServer=lpHandle->lpServer; if (lpServer->EventsInfo.dwClients) { rfbClientIteratorPtr i=rfbGetClientIteratorWithClosed(lpServer->rfbScreen); rfbClientPtr cl=rfbClientIteratorHead(i); while (cl) { rfbClientPtr clPrev=cl; cl=rfbClientIteratorNext(i); rfbClientConnectionGone(clPrev); } rfbReleaseClientIterator(i); } return; }
// We call this to see if we have a new cursor and should notify clients to do an update // Or if cursor has moved void rfbCheckForCursorChange() { CGPoint cursorLoc = currentCursorLoc(); //rfbLog("Check For Cursor Change"); // First Let's see if we have new info on the pasteboard - if so we'll send an update to each client if (lastCursorSeed != CGSCurrentCursorSeed() || !CGPointEqualToPoint(lastCursorPosition, cursorLoc)) { rfbClientIteratorPtr iterator = rfbGetClientIterator(); rfbClientPtr cl; // Record first in case another change occurs after notifying clients lastCursorSeed = CGSCurrentCursorSeed(); lastCursorPosition = cursorLoc; // Notify each client while ((cl = rfbClientIteratorNext(iterator)) != NULL) { if (rfbShouldSendNewCursor(cl) || (rfbShouldSendNewPosition(cl))) pthread_cond_signal(&cl->updateCond); } rfbReleaseClientIterator(iterator); } }
void rfbProcessEvents(rfbScreenInfoPtr rfbScreen,long usec) { rfbClientIteratorPtr i; rfbClientPtr cl,clPrev; if(usec<0) usec=rfbScreen->rfbDeferUpdateTime*1000; rfbCheckFds(rfbScreen,usec); i = rfbGetClientIterator(rfbScreen); cl=rfbClientIteratorHead(i); while(cl) { rfbUpdateClient(cl); clPrev=cl; cl=rfbClientIteratorNext(i); if(clPrev->sock==-1) rfbClientConnectionGone(clPrev); } rfbReleaseClientIterator(i); }
void rfbNewFramebuffer(rfbScreenInfoPtr screen, char *framebuffer, int width, int height, int bitsPerSample, int samplesPerPixel, int bytesPerPixel) { rfbPixelFormat old_format; rfbBool format_changed = FALSE; rfbClientIteratorPtr iterator; rfbClientPtr cl; /* Update information in the screenInfo structure */ old_format = screen->serverFormat; if (width & 3) rfbErr("WARNING: New width (%d) is not a multiple of 4.\n", width); screen->width = width; screen->height = height; screen->bitsPerPixel = screen->depth = 8*bytesPerPixel; screen->paddedWidthInBytes = width*bytesPerPixel; rfbInitServerFormat(screen, bitsPerSample); if (memcmp(&screen->serverFormat, &old_format, sizeof(rfbPixelFormat)) != 0) { format_changed = TRUE; } screen->frameBuffer = framebuffer; /* Adjust pointer position if necessary */ if (screen->cursorX >= width) screen->cursorX = width - 1; if (screen->cursorY >= height) screen->cursorY = height - 1; /* For each client: */ iterator = rfbGetClientIterator(screen); while ((cl = rfbClientIteratorNext(iterator)) != NULL) { /* Re-install color translation tables if necessary */ if (format_changed) screen->setTranslateFunction(cl); /* Mark the screen contents as changed, and schedule sending NewFBSize message if supported by this client. */ LOCK(cl->updateMutex); sraRgnDestroy(cl->modifiedRegion); cl->modifiedRegion = sraRgnCreateRect(0, 0, width, height); sraRgnMakeEmpty(cl->copyRegion); cl->copyDX = 0; cl->copyDY = 0; if (cl->useNewFBSize) cl->newFBSizePending = TRUE; TSIGNAL(cl->updateCond); UNLOCK(cl->updateMutex); } rfbReleaseClientIterator(iterator); }
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(!cl->enableCursorShapeUpdates) { /* * n.b. (dx, dy) is the vector pointing in the direction the * copyrect displacement will take place. copyRegion is the * destination rectangle (say), not the source rectangle. */ sraRegionPtr cursorRegion; int x = cl->cursorX - cl->screen->cursor->xhot; int y = cl->cursorY - cl->screen->cursor->yhot; int w = cl->screen->cursor->width; int h = cl->screen->cursor->height; cursorRegion = sraRgnCreateRect(x, y, x + w, y + h); sraRgnAnd(cursorRegion, cl->copyRegion); if(!sraRgnEmpty(cursorRegion)) { /* * current cursor rect overlaps with the copy region *dest*, * mark it as modified since we won't copy-rect stuff to it. */ sraRgnOr(cl->modifiedRegion, cursorRegion); } sraRgnDestroy(cursorRegion); cursorRegion = sraRgnCreateRect(x, y, x + w, y + h); /* displace it to check for overlap with copy region source: */ sraRgnOffset(cursorRegion, dx, dy); sraRgnAnd(cursorRegion, cl->copyRegion); if(!sraRgnEmpty(cursorRegion)) { /* * current cursor rect overlaps with the copy region *source*, * mark the *displaced* cursorRegion as modified since we * won't copyrect stuff to it. */ sraRgnOr(cl->modifiedRegion, cursorRegion); } sraRgnDestroy(cursorRegion); } } else { sraRgnOr(cl->modifiedRegion,copyRegion); } TSIGNAL(cl->updateCond); UNLOCK(cl->updateMutex); } rfbReleaseClientIterator(iterator); }
void VncServer::encodeAndSend(int viewNum, int x0, int y0, int w, int h, const VncServer::ViewParameters ¶m, bool lastView) { //std::cerr << "encodeAndSend: view=" << viewNum << ", c=" << (void *)rgba(viewNum) << ", d=" << depth(viewNum) << std::endl; if (!m_resizeBlocked) { m_firstTile = true; } m_resizeBlocked = true; //vistle::StopWatch timer("encodeAndSend"); const int tileWidth = m_tileWidth, tileHeight = m_tileHeight; static int framecount=0; ++framecount; for (int y=y0; y<y0+h; y+=tileHeight) { for (int x=x0; x<x0+w; x+=tileWidth) { // depth auto dt = new(tbb::task::allocate_root()) EncodeTask(m_resultQueue, viewNum, x, y, std::min(tileWidth, x0+w-x), std::min(tileHeight, y0+h-y), depth(viewNum), m_imageParam, param); tbb::task::enqueue(*dt); ++m_queuedTiles; // color auto ct = new(tbb::task::allocate_root()) EncodeTask(m_resultQueue, viewNum, x, y, std::min(tileWidth, x0+w-x), std::min(tileHeight, y0+h-y), rgba(viewNum), m_imageParam, param); tbb::task::enqueue(*ct); ++m_queuedTiles; } } bool tileReady = false; do { VncServer::EncodeResult result; tileReady = false; if (m_resultQueue.try_pop(result)) { --m_queuedTiles; tileReady = true; if (result.message) { tileMsg &msg = *result.message; if (m_firstTile) { msg.flags |= rfbTileFirst; //std::cerr << "first tile: req=" << msg.requestNumber << std::endl; } m_firstTile = false; if (m_queuedTiles == 0 && lastView) { msg.flags |= rfbTileLast; //std::cerr << "last tile: req=" << msg.requestNumber << std::endl; } msg.frameNumber = framecount; rfbCheckFds(m_screen, 0); rfbHttpCheckFds(m_screen); rfbClientIteratorPtr i = rfbGetClientIterator(m_screen); while (rfbClientPtr cl = rfbClientIteratorNext(i)) { if (cl->clientData) { rfbUpdateClient(cl); if (rfbWriteExact(cl, (char *)&msg, sizeof(msg)) < 0) { rfbLogPerror("sendTileMessage: write header"); } if (result.payload && msg.size > 0) { if (rfbWriteExact(cl, result.payload, msg.size) < 0) { rfbLogPerror("sendTileMessage: write paylod"); } } } rfbUpdateClient(cl); } rfbReleaseClientIterator(i); } delete[] result.payload; delete result.message; } } while (m_queuedTiles > 0 && (tileReady || lastView)); if (lastView) { vassert(m_queuedTiles == 0); m_resizeBlocked = false; deferredResize(); } //sleep(1); }
int rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec) { int nfds; fd_set fds; struct timeval tv; struct sockaddr_in addr; socklen_t addrlen = sizeof(addr); char buf[6]; const int one = 1; int sock; rfbClientIteratorPtr i; rfbClientPtr cl; struct timeval tv_msg; fd_set fds_msg; int nfds_msg; int result = 0; if (!rfbScreen->inetdInitDone && rfbScreen->inetdSock != -1) { rfbNewClientConnection(rfbScreen,rfbScreen->inetdSock); rfbScreen->inetdInitDone = TRUE; } do { memcpy((char *)&fds, (char *)&(rfbScreen->allFds), sizeof(fd_set)); tv.tv_sec = 0; tv.tv_usec = usec; nfds = select(rfbScreen->maxFd + 1, &fds, NULL, NULL /* &fds */, &tv); if (nfds == 0) { /* timed out, check for async events */ i = rfbGetClientIterator(rfbScreen); while((cl = rfbClientIteratorNext(i))) { if (cl->onHold) continue; if (FD_ISSET(cl->sock, &(rfbScreen->allFds))) rfbSendFileTransferChunk(cl); } rfbReleaseClientIterator(i); return result; } if (nfds < 0) { #ifdef WIN32 errno = WSAGetLastError(); #endif if (errno != EINTR) rfbLogPerror("rfbCheckFds: select"); return -1; } result += nfds; if (rfbScreen->listenSock != -1 && FD_ISSET(rfbScreen->listenSock, &fds)) { if ((sock = accept(rfbScreen->listenSock, (struct sockaddr *)&addr, &addrlen)) < 0) { rfbLogPerror("rfbCheckFds: accept"); return -1; } #ifndef WIN32 if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) { rfbLogPerror("rfbCheckFds: fcntl"); closesocket(sock); return -1; } #endif if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof(one)) < 0) { rfbLogPerror("rfbCheckFds: setsockopt"); closesocket(sock); return -1; } #ifdef USE_LIBWRAP if(!hosts_ctl("vnc",STRING_UNKNOWN,inet_ntoa(addr.sin_addr), STRING_UNKNOWN)) { rfbLog("Rejected connection from client %s\n", inet_ntoa(addr.sin_addr)); closesocket(sock); return -1; } #endif rfbLog("Got connection from client %s\n", inet_ntoa(addr.sin_addr)); rfbNewClient(rfbScreen,sock); FD_CLR(rfbScreen->listenSock, &fds); if (--nfds == 0) return result; } if ((rfbScreen->udpSock != -1) && FD_ISSET(rfbScreen->udpSock, &fds)) { if(!rfbScreen->udpClient) rfbNewUDPClient(rfbScreen); if (recvfrom(rfbScreen->udpSock, buf, 1, MSG_PEEK, (struct sockaddr *)&addr, &addrlen) < 0) { rfbLogPerror("rfbCheckFds: UDP: recvfrom"); rfbDisconnectUDPSock(rfbScreen); rfbScreen->udpSockConnected = FALSE; } else { if (!rfbScreen->udpSockConnected || (memcmp(&addr, &rfbScreen->udpRemoteAddr, addrlen) != 0)) { /* new remote end */ rfbLog("rfbCheckFds: UDP: got connection\n"); memcpy(&rfbScreen->udpRemoteAddr, &addr, addrlen); rfbScreen->udpSockConnected = TRUE; if (connect(rfbScreen->udpSock, (struct sockaddr *)&addr, addrlen) < 0) { rfbLogPerror("rfbCheckFds: UDP: connect"); rfbDisconnectUDPSock(rfbScreen); return -1; } rfbNewUDPConnection(rfbScreen,rfbScreen->udpSock); } rfbProcessUDPInput(rfbScreen); } FD_CLR(rfbScreen->udpSock, &fds); if (--nfds == 0) return result; } i = rfbGetClientIterator(rfbScreen); while((cl = rfbClientIteratorNext(i))) { if (cl->onHold) continue; if (FD_ISSET(cl->sock, &(rfbScreen->allFds))) { if (FD_ISSET(cl->sock, &fds)) { tv_msg.tv_sec = 0; tv_msg.tv_usec = 0; FD_ZERO(&fds_msg); FD_SET(cl->sock, &fds_msg); do { /* drain all messages, speed up mouse move processing */ rfbProcessClientMessage(cl); nfds_msg = select(cl->sock + 1, &fds_msg, NULL, NULL, &tv_msg); } while (nfds_msg > 0); } else rfbSendFileTransferChunk(cl); } } rfbReleaseClientIterator(i); } while(rfbScreen->handleEventsEagerly); return result; }
int rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec) { int nfds; fd_set fds; struct timeval tv; struct sockaddr_in addr; socklen_t addrlen = sizeof(addr); char buf[6]; rfbClientIteratorPtr i; rfbClientPtr cl; int result = 0; if (!rfbScreen->inetdInitDone && rfbScreen->inetdSock != -1) { rfbNewClientConnection(rfbScreen,rfbScreen->inetdSock); rfbScreen->inetdInitDone = TRUE; } do { memcpy((char *)&fds, (char *)&(rfbScreen->allFds), sizeof(fd_set)); tv.tv_sec = 0; tv.tv_usec = usec; nfds = select(rfbScreen->maxFd + 1, &fds, NULL, NULL /* &fds */, &tv); if (nfds == 0) { /* timed out, check for async events */ i = rfbGetClientIterator(rfbScreen); while((cl = rfbClientIteratorNext(i))) { if (cl->onHold) continue; if (FD_ISSET(cl->sock, &(rfbScreen->allFds))) rfbSendFileTransferChunk(cl); } rfbReleaseClientIterator(i); return result; } if (nfds < 0) { #ifdef WIN32 errno = WSAGetLastError(); #endif if (errno != EINTR) rfbLogPerror("rfbCheckFds: select"); return -1; } result += nfds; if (rfbScreen->listenSock != -1 && FD_ISSET(rfbScreen->listenSock, &fds)) { if (!rfbProcessNewConnection(rfbScreen)) return -1; FD_CLR(rfbScreen->listenSock, &fds); if (--nfds == 0) return result; } if (rfbScreen->listen6Sock != -1 && FD_ISSET(rfbScreen->listen6Sock, &fds)) { if (!rfbProcessNewConnection(rfbScreen)) return -1; FD_CLR(rfbScreen->listen6Sock, &fds); if (--nfds == 0) return result; } if ((rfbScreen->udpSock != -1) && FD_ISSET(rfbScreen->udpSock, &fds)) { if(!rfbScreen->udpClient) rfbNewUDPClient(rfbScreen); if (recvfrom(rfbScreen->udpSock, buf, 1, MSG_PEEK, (struct sockaddr *)&addr, &addrlen) < 0) { rfbLogPerror("rfbCheckFds: UDP: recvfrom"); rfbDisconnectUDPSock(rfbScreen); rfbScreen->udpSockConnected = FALSE; } else { if (!rfbScreen->udpSockConnected || (memcmp(&addr, &rfbScreen->udpRemoteAddr, addrlen) != 0)) { /* new remote end */ rfbLog("rfbCheckFds: UDP: got connection\n"); memcpy(&rfbScreen->udpRemoteAddr, &addr, addrlen); rfbScreen->udpSockConnected = TRUE; if (connect(rfbScreen->udpSock, (struct sockaddr *)&addr, addrlen) < 0) { rfbLogPerror("rfbCheckFds: UDP: connect"); rfbDisconnectUDPSock(rfbScreen); return -1; } rfbNewUDPConnection(rfbScreen,rfbScreen->udpSock); } rfbProcessUDPInput(rfbScreen); } FD_CLR(rfbScreen->udpSock, &fds); if (--nfds == 0) return result; } i = rfbGetClientIterator(rfbScreen); while((cl = rfbClientIteratorNext(i))) { if (cl->onHold) continue; if (FD_ISSET(cl->sock, &(rfbScreen->allFds))) { if (FD_ISSET(cl->sock, &fds)) rfbProcessClientMessage(cl); else rfbSendFileTransferChunk(cl); } } rfbReleaseClientIterator(i); } while(rfbScreen->handleEventsEagerly); return result; }