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 _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); }
//! 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); }
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 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 }
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); }
//! 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 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 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 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 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); }
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); }
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); }
// 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 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 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 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 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); }
void GsSelect(GR_TIMEOUT timeout) { fd_set rfds; int e; int setsize = 0; struct timeval tout; struct timeval *to; #if NONETWORK int fd; #endif #if HAVE_VNCSERVER #if VNCSERVER_PTHREADED int dummy; #else rfbClientIteratorPtr i; rfbClientPtr cl; #endif #endif /* X11/SDL perform single update of aggregate screen update region*/ if (scrdev.PreSelect) { /* returns # pending events*/ if (scrdev.PreSelect(&scrdev)) { /* poll for mouse data and service if found*/ while (GsCheckMouseEvent()) continue; /* poll for keyboard data and service if found*/ while (GsCheckKeyboardEvent()) continue; /* events found, return with no sleep*/ return; } } /* Set up the FDs for use in the main select(): */ FD_ZERO(&rfds); if(mouse_fd >= 0) { FD_SET(mouse_fd, &rfds); if (mouse_fd > setsize) setsize = mouse_fd; } if(keyb_fd >= 0) { FD_SET(keyb_fd, &rfds); if (keyb_fd > setsize) setsize = keyb_fd; } #if MW_FEATURE_TWO_KEYBOARDS if(keyb2_fd >= 0) { FD_SET(keyb2_fd, &rfds); if (keyb2_fd > setsize) setsize = keyb2_fd; } #endif #if NONETWORK /* handle registered input file descriptors*/ for (fd = 0; fd < regfdmax; fd++) { if (!FD_ISSET(fd, ®fdset)) continue; FD_SET(fd, &rfds); if (fd > setsize) setsize = fd; } #else /* !NONETWORK */ /* handle client socket connections*/ FD_SET(un_sock, &rfds); if (un_sock > setsize) setsize = un_sock; curclient = root_client; while(curclient) { if(curclient->waiting_for_event && curclient->eventhead) { curclient->waiting_for_event = FALSE; GrGetNextEventWrapperFinish(curclient->id); return; } FD_SET(curclient->id, &rfds); if(curclient->id > setsize) setsize = curclient->id; curclient = curclient->next; } #endif /* NONETWORK */ #if HAVE_VNCSERVER #if VNCSERVER_PTHREADED /* Add file vnc thread fd. This is useful to force handling of events generated by the VNC thread*/ FD_SET( vnc_thread_fd, &(rfds) ); if ( vnc_thread_fd > setsize ) setsize = vnc_thread_fd; #else /* Add all VNC open sockets to nano-X select set */ FD_SET( rfbScreen->listenSock, &(rfds) ); if ( rfbScreen->listenSock > setsize ) setsize = rfbScreen->listenSock; FD_SET( rfbScreen->httpListenSock, &(rfds) ); if ( rfbScreen->httpListenSock > setsize ) setsize = rfbScreen->httpListenSock; i = rfbGetClientIterator(rfbScreen); cl = rfbClientIteratorNext(i); while ( cl ) { if ( cl->sock >= 0 ) { FD_SET( cl->sock, &(rfds) ); if ( cl->sock > setsize ) setsize = cl->sock; } cl = rfbClientIteratorNext(i); } rfbReleaseClientIterator(i); #endif #endif /* HAVE_VNCSERVER*/ /* setup timeval struct for block or poll in select()*/ tout.tv_sec = tout.tv_usec = 0; /* setup for assumed poll*/ to = &tout; int poll = (timeout == (GR_TIMEOUT) -1L); /* timeout = -1 means just poll*/ if (!poll) { #if MW_FEATURE_TIMERS /* get next timer or use passed timeout and convert to timeval struct*/ if (!GdGetNextTimeout(&tout, timeout)) /* no app timers or VTSWITCH?*/ #else if (timeout) /* setup mwin poll timer*/ { /* convert wait timeout to timeval struct*/ tout.tv_sec = timeout / 1000; tout.tv_usec = (timeout % 1000) * 1000; } else #endif { to = NULL; /* no timers, block*/ } } /* some drivers can't block in select as backend is poll based (SDL)*/ if (scrdev.flags & PSF_CANTBLOCK) { #define WAITTIME 100 /* check if would block permanently or timeout > WAITTIME*/ if (to == NULL || tout.tv_sec != 0 || tout.tv_usec > WAITTIME) { /* override timeouts and wait for max WAITTIME ms*/ to = &tout; tout.tv_sec = 0; tout.tv_usec = WAITTIME; } } /* Wait for some input on any of the fds in the set or a timeout*/ #if NONETWORK SERVER_UNLOCK(); /* allow other threads to run*/ #endif e = select(setsize+1, &rfds, NULL, NULL, to); #if NONETWORK SERVER_LOCK(); #endif if(e > 0) /* input ready*/ { /* service mouse file descriptor*/ if(mouse_fd >= 0 && FD_ISSET(mouse_fd, &rfds)) while(GsCheckMouseEvent()) continue; /* service keyboard file descriptor*/ if( (keyb_fd >= 0 && FD_ISSET(keyb_fd, &rfds)) #if MW_FEATURE_TWO_KEYBOARDS || (keyb2_fd >= 0 && FD_ISSET(keyb2_fd, &rfds)) #endif ) while(GsCheckKeyboardEvent()) continue; #if HAVE_VNCSERVER && VNCSERVER_PTHREADED if(vnc_thread_fd >= 0 && FD_ISSET(vnc_thread_fd, &rfds)) /* Read from vnc pipe */ read( vnc_thread_fd, &dummy, sizeof(int)); #endif #if NONETWORK /* check for input on registered file descriptors */ for (fd = 0; fd < regfdmax; fd++) { GR_EVENT_FDINPUT * gp; if (!FD_ISSET(fd, ®fdset) || !FD_ISSET(fd, &rfds)) continue; gp = (GR_EVENT_FDINPUT *)GsAllocEvent(curclient); if(gp) { gp->type = GR_EVENT_TYPE_FDINPUT; gp->fd = fd; } } #else /* !NONETWORK */ /* If a client is trying to connect, accept it: */ if(FD_ISSET(un_sock, &rfds)) GsAcceptClient(); /* If a client is sending us a command, handle it: */ curclient = root_client; while (curclient) { GR_CLIENT *curclient_next; /* curclient may be freed in GsDropClient*/ curclient_next = curclient->next; if(FD_ISSET(curclient->id, &rfds)) GsHandleClient(curclient->id); curclient = curclient_next; } #if HAVE_VNCSERVER && !VNCSERVER_PTHREADED rfbProcessEvents(rfbScreen, 0); #endif #endif /* NONETWORK */ } else if (e == 0) /* timeout*/ { #if NONETWORK /* * Timeout has occured. Currently return a timeout event * regardless of whether client has selected for it. * Note: this will be changed back to GR_EVENT_TYPE_NONE * for the GrCheckNextEvent/LINK_APP_TO_SERVER case */ #if MW_FEATURE_TIMERS if(GdTimeout()) #endif { GR_EVENT_GENERAL * gp; if ((gp = (GR_EVENT_GENERAL *)GsAllocEvent(curclient)) != NULL) gp->type = GR_EVENT_TYPE_TIMEOUT; } #else /* !NONETWORK */ #if MW_FEATURE_TIMERS /* check for timer timeouts and service if found*/ GdTimeout(); #endif #endif /* NONETWORK */ } else if(errno != EINTR) EPRINTF("Select() call in main failed\n"); }
void measure_send_rates(int init) { double cmp_rate, raw_rate; static double now, start = 0.0; static rfbDisplayHookPtr orig_display_hook = NULL; double cmp_max = 1.0e+08; /* 100 MB/sec */ double cmp_min = 1000.0; /* 9600baud */ double lat_max = 5.0; /* 5 sec */ double lat_min = .0005; /* 0.5 ms */ int min_cmp = 10000, nclients; rfbClientIteratorPtr iter; rfbClientPtr cl0, cl; int msg = 0, clcnt0 = 0, cc; int db = 0, ouch_db = 0, ouch = 0; if (! measure_speeds) { return; } if (speeds_net_rate && speeds_net_latency) { return; } if (!client_count) { return; } if (! orig_display_hook) { orig_display_hook = screen->displayHook; } if (start == 0.0) { dtime(&start); } dtime0(&now); if (now < last_client_gone+4.0) { return; } now = now - start; nclients = 0; if (!screen) { return; } cl0 = NULL; iter = rfbGetClientIterator(screen); while( (cl = rfbClientIteratorNext(iter)) ) { ClientData *cd = (ClientData *) cl->clientData; if (! cd) { continue; } if (cd->send_cmp_rate > 0.0) { continue; } if (cl->onHold) { continue; } nclients++; if (cl0 == NULL) { cl0 = cl; } } rfbReleaseClientIterator(iter); cl = cl0; cc = 0; while (cl != NULL && cc++ == 0) { int defer, i, cbs, rbs; char *httpdir; double dt, dt1 = 0.0, dt2, dt3; double tm, spin_max = 15.0, spin_lat_max = 1.5; int got_t2 = 0, got_t3 = 0; ClientData *cd = (ClientData *) cl->clientData; #if 0 for (i=0; i<MAX_ENCODINGS; i++) { cbs += cl->bytesSent[i]; } rbs = cl->rawBytesEquivalent; #else #if LIBVNCSERVER_HAS_STATS cbs = rfbStatGetSentBytes(cl); rbs = rfbStatGetSentBytesIfRaw(cl); #endif #endif if (init) { if (db) fprintf(stderr, "%d client num rects req: %d mod: %d cbs: %d " "rbs: %d dt1: %.3f t: %.3f\n", init, (int) sraRgnCountRects(cl->requestedRegion), (int) sraRgnCountRects(cl->modifiedRegion), cbs, rbs, dt1, now); cd->timer = dnow(); cd->cmp_bytes_sent = cbs; cd->raw_bytes_sent = rbs; continue; } /* first part of the bulk transfer of initial screen */ dt1 = dtime(&cd->timer); if (db) fprintf(stderr, "%d client num rects req: %d mod: %d cbs: %d " "rbs: %d dt1: %.3f t: %.3f\n", init, (int) sraRgnCountRects(cl->requestedRegion), (int) sraRgnCountRects(cl->modifiedRegion), cbs, rbs, dt1, now); if (dt1 <= 0.0) { continue; } cbs = cbs - cd->cmp_bytes_sent; rbs = rbs - cd->raw_bytes_sent; if (cbs < min_cmp) { continue; } if (ouch_db) fprintf(stderr, "START-OUCH: %d\n", client_count); clcnt0 = client_count; #define OUCH ( ouch || (ouch = (!client_count || client_count != clcnt0 || dnow() < last_client_gone+4.0)) ) rfbPE(1000); if (OUCH && ouch_db) fprintf(stderr, "***OUCH-A\n"); if (OUCH) continue; if (use_threads) LOCK(cl->updateMutex); if (sraRgnCountRects(cl->modifiedRegion)) { rfbPE(1000); if (OUCH && ouch_db) fprintf(stderr, "***OUCH-B\n"); if (use_threads) UNLOCK(cl->updateMutex); if (OUCH) continue; } if (use_threads) UNLOCK(cl->updateMutex); defer = screen->deferUpdateTime; httpdir = screen->httpDir; screen->deferUpdateTime = 0; screen->httpDir = NULL; /* mark a small rectangle: */ mark_rect_as_modified(0, 0, 16, 16, 1); dtime0(&tm); dt2 = 0.0; dt3 = 0.0; if (dt1 < 0.25) { /* try to cut it down to avoid long pauses. */ spin_max = 5.0; } /* when req1 = 1 mod1 == 0, end of 2nd part of bulk transfer */ while (1) { int req0, req1, mod0, mod1; if (OUCH && ouch_db) fprintf(stderr, "***OUCH-C1\n"); if (OUCH) break; if (use_threads) LOCK(cl->updateMutex); req0 = sraRgnCountRects(cl->requestedRegion); mod0 = sraRgnCountRects(cl->modifiedRegion); if (use_threads) UNLOCK(cl->updateMutex); if (use_threads) { usleep(1000); } else { if (mod0) { rfbPE(1000); } else { rfbCFD(1000); } } dt = dtime(&tm); dt2 += dt; if (dt2 > spin_max) { break; } if (OUCH && ouch_db) fprintf(stderr, "***OUCH-C2\n"); if (OUCH) break; if (use_threads) LOCK(cl->updateMutex); req1 = sraRgnCountRects(cl->requestedRegion); mod1 = sraRgnCountRects(cl->modifiedRegion); if (use_threads) UNLOCK(cl->updateMutex); if (db) fprintf(stderr, "dt2 calc: num rects req: %d/%d mod: %d/%d " "fbu-sent: %d dt: %.4f dt2: %.4f tm: %.4f\n", req0, req1, mod0, mod1, #if 0 cl->framebufferUpdateMessagesSent, #else #if LIBVNCSERVER_HAS_STATS rfbStatGetMessageCountSent(cl, rfbFramebufferUpdate), #endif #endif dt, dt2, tm); if (req1 != 0 && mod1 == 0) { got_t2 = 1; break; } } if (OUCH && ouch_db) fprintf(stderr, "***OUCH-D\n"); if (OUCH) goto ouch; if (! got_t2) { dt2 = 0.0; } else { int tr, trm = 3; double dts[10]; /* * Note: since often select(2) cannot sleep * less than 1/HZ (e.g. 10ms), the resolution * of the latency may be messed up by something * of this order. Effect may occur on both ends, * i.e. the viewer may not respond immediately. */ for (tr = 0; tr < trm; tr++) { usleep(5000); /* mark a 2nd small rectangle: */ mark_rect_as_modified(0, 0, 16, 16, 1); i = 0; dtime0(&tm); dt3 = 0.0; /* * when req1 > 0 and mod1 == 0, we say * that is the "ping" time. */ while (1) { int req0, req1, mod0, mod1; if (use_threads) LOCK(cl->updateMutex); req0 = sraRgnCountRects(cl->requestedRegion); mod0 = sraRgnCountRects(cl->modifiedRegion); if (use_threads) UNLOCK(cl->updateMutex); if (i == 0) { rfbPE(0); } else { if (use_threads) { usleep(1000); } else { /* try to get it all */ rfbCFD(1000*1000); } } if (OUCH && ouch_db) fprintf(stderr, "***OUCH-E\n"); if (OUCH) goto ouch; dt = dtime(&tm); i++; dt3 += dt; if (dt3 > spin_lat_max) { break; } if (use_threads) LOCK(cl->updateMutex); req1 = sraRgnCountRects(cl->requestedRegion); mod1 = sraRgnCountRects(cl->modifiedRegion); if (use_threads) UNLOCK(cl->updateMutex); if (db) fprintf(stderr, "dt3 calc: num rects req: %d/%d mod: %d/%d " "fbu-sent: %d dt: %.4f dt3: %.4f tm: %.4f\n", req0, req1, mod0, mod1, #if 0 cl->framebufferUpdateMessagesSent, #else #if LIBVNCSERVER_HAS_STATS rfbStatGetMessageCountSent(cl, rfbFramebufferUpdate), #endif #endif dt, dt3, tm); if (req1 != 0 && mod1 == 0) { dts[got_t3++] = dt3; break; } } } if (! got_t3) { dt3 = 0.0; } else { if (got_t3 == 1) { dt3 = dts[0]; } else if (got_t3 == 2) { dt3 = dts[1]; } else { if (dts[2] > 0.0) { double rat = dts[1]/dts[2]; if (rat > 0.5 && rat < 2.0) { dt3 = dts[1]+dts[2]; dt3 *= 0.5; } else { dt3 = dts[1]; } } else { dt3 = dts[1]; } } } } ouch: screen->deferUpdateTime = defer; screen->httpDir = httpdir; if (OUCH && ouch_db) fprintf(stderr, "***OUCH-F\n"); if (OUCH) break; dt = dt1 + dt2; if (dt3 <= dt2/2.0) { /* guess only 1/2 a ping for reply... */ dt = dt - dt3/2.0; } cmp_rate = cbs/dt; raw_rate = rbs/dt; if (cmp_rate > cmp_max) { cmp_rate = cmp_max; } if (cmp_rate <= cmp_min) { cmp_rate = cmp_min; } cd->send_cmp_rate = cmp_rate; cd->send_raw_rate = raw_rate; if (dt3 > lat_max) { dt3 = lat_max; } if (dt3 <= lat_min) { dt3 = lat_min; } cd->latency = dt3; rfbLog("client %d network rate %.1f KB/sec (%.1f eff KB/sec)\n", cd->uid, cmp_rate/1000.0, raw_rate/1000.0); rfbLog("client %d latency: %.1f ms\n", cd->uid, 1000.0*dt3); rfbLog("dt1: %.4f, dt2: %.4f dt3: %.4f bytes: %d\n", dt1, dt2, dt3, cbs); msg = 1; } if (msg) { int link, latency, netrate; char *str = "error"; link = link_rate(&latency, &netrate); if (link == LR_UNSET) { str = "LR_UNSET"; } else if (link == LR_UNKNOWN) { str = "LR_UNKNOWN"; } else if (link == LR_DIALUP) { str = "LR_DIALUP"; } else if (link == LR_BROADBAND) { str = "LR_BROADBAND"; } else if (link == LR_LAN) { str = "LR_LAN"; } rfbLog("link_rate: %s - %d ms, %d KB/s\n", str, latency, netrate); } if (init) { if (nclients) { screen->displayHook = measure_display_hook; } } else { screen->displayHook = orig_display_hook; } }
static int get_rate(int which) { rfbClientIteratorPtr iter; rfbClientPtr cl; int irate, irate_min = 1; /* 1 KB/sec */ int irate_max = 100000; /* 100 MB/sec */ int count = 0; double slowest = -1.0, rate; static double save_rate = 1000 * NETRATE0; 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->send_cmp_rate == 0.0 || cd->send_raw_rate == 0.0) { continue; } count++; if (which == 0) { rate = cd->send_cmp_rate; } else { rate = cd->send_raw_rate; } if (slowest == -1.0 || rate < slowest) { slowest = rate; } } rfbReleaseClientIterator(iter); if (! count) { return NETRATE0; } if (slowest == -1.0) { slowest = save_rate; } else { save_rate = slowest; } irate = (int) (slowest/1000.0); if (irate < irate_min) { irate = irate_min; } if (irate > irate_max) { irate = irate_max; } if (0) fprintf(stderr, "get_rate(%d) %d %.3f/%.3f\n", which, irate, save_rate, slowest); return irate; }
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; }
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); }
int main(int argc,char** argv) { int i,j; time_t t; rfbScreenInfoPtr server; rfbClientLog=rfbTestLog; rfbClientErr=rfbTestLog; /* Initialize server */ server=rfbGetScreen(&argc,argv,width,height,8,3,4); server->frameBuffer=malloc(400*300*4); server->cursor=NULL; for(j=0;j<400*300*4;j++) server->frameBuffer[j]=j; rfbInitServer(server); rfbProcessEvents(server,0); initStatistics(); #ifndef ALL_AT_ONCE for(i=0;i<NUMBER_OF_ENCODINGS_TO_TEST;i++) { #else /* Initialize clients */ for(i=0;i<NUMBER_OF_ENCODINGS_TO_TEST;i++) #endif startClient(i,server); t=time(NULL); /* test 20 seconds */ while(time(NULL)-t<20) { idle(server); rfbProcessEvents(server,1); } rfbLog("%d failed, %d received\n",totalFailed,totalCount); #ifndef ALL_AT_ONCE { rfbClientPtr cl; rfbClientIteratorPtr iter=rfbGetClientIterator(server); while((cl=rfbClientIteratorNext(iter))) rfbCloseClient(cl); rfbReleaseClientIterator(iter); } } #endif rfbScreenCleanup(server); for(i=0;i<thread_counter;i++) pthread_join(all_threads[i], NULL); free(server->frameBuffer); rfbLog("Statistics:\n"); for(i=0;i<NUMBER_OF_ENCODINGS_TO_TEST;i++) rfbLog("%s encoding: %d failed, %d received\n", testEncodings[i].str,statistics[1][i],statistics[0][i]); if(totalFailed) return 1; return(0); }