Beispiel #1
0
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);
  }
}
Beispiel #2
0
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);
}
Beispiel #3
0
//! 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);
}
Beispiel #5
0
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);
}
Beispiel #7
0
//! 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);
}
Beispiel #8
0
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;
}
Beispiel #9
0
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);
}
Beispiel #10
0
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;
}
Beispiel #11
0
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);
}
Beispiel #12
0
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);
}
Beispiel #13
0
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);
}
Beispiel #14
0
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);
}
Beispiel #15
0
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);
}
Beispiel #16
0
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);
}
Beispiel #17
0
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);
}
Beispiel #18
0
// 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);
    }
}
Beispiel #19
0
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);
}
Beispiel #20
0
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);
}
Beispiel #21
0
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);
}
Beispiel #22
0
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);
}
Beispiel #23
0
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, &regfdset))
			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, &regfdset)  ||  !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");
}
Beispiel #24
0
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;
	}
}
Beispiel #25
0
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;
}
Beispiel #26
0
void VncServer::encodeAndSend(int viewNum, int x0, int y0, int w, int h, const VncServer::ViewParameters &param, 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);
}
Beispiel #27
0
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;
}
Beispiel #28
0
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;
}
Beispiel #29
0
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);
}