Exemple #1
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);

#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);
}
Exemple #2
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);
}
Exemple #3
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);
}
Exemple #4
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);
}
Exemple #5
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;
}
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;
}
Exemple #7
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;
}
Exemple #8
0
rfbBool
rfbProcessEvents(rfbScreenInfoPtr screen,long usec)
{
  rfbClientIteratorPtr i;
  rfbClientPtr cl,clPrev;
  struct timeval tv;
  rfbBool result=FALSE;
  extern rfbClientIteratorPtr
    rfbGetClientIteratorWithClosed(rfbScreenInfoPtr rfbScreen);

  if(usec<0)
    usec=screen->deferUpdateTime*1000;

  rfbCheckFds(screen,usec);
  rfbHttpCheckFds(screen);

  i = rfbGetClientIteratorWithClosed(screen);
  cl=rfbClientIteratorHead(i);
  while(cl) {
    if (cl->sock >= 0 && !cl->onHold && FB_UPDATE_PENDING(cl) &&
        !sraRgnEmpty(cl->requestedRegion)) {
      result=TRUE;
      if(screen->deferUpdateTime == 0) {
	  rfbSendFramebufferUpdate(cl,cl->modifiedRegion);
      } else if(cl->startDeferring.tv_usec == 0) {
	gettimeofday(&cl->startDeferring,NULL);
	if(cl->startDeferring.tv_usec == 0)
	  cl->startDeferring.tv_usec++;
      } else {
	gettimeofday(&tv,NULL);
	if(tv.tv_sec < cl->startDeferring.tv_sec /* at midnight */
	   || ((tv.tv_sec-cl->startDeferring.tv_sec)*1000
	       +(tv.tv_usec-cl->startDeferring.tv_usec)/1000)
	     > screen->deferUpdateTime) {
	  cl->startDeferring.tv_usec = 0;
	  rfbSendFramebufferUpdate(cl,cl->modifiedRegion);
	}
      }
    }

    if (!cl->viewOnly && cl->lastPtrX >= 0) {
      if(cl->startPtrDeferring.tv_usec == 0) {
        gettimeofday(&cl->startPtrDeferring,NULL);
        if(cl->startPtrDeferring.tv_usec == 0)
          cl->startPtrDeferring.tv_usec++;
      } else {
        struct timeval tv;
        gettimeofday(&tv,NULL);
        if(tv.tv_sec < cl->startPtrDeferring.tv_sec /* at midnight */
           || ((tv.tv_sec-cl->startPtrDeferring.tv_sec)*1000
           +(tv.tv_usec-cl->startPtrDeferring.tv_usec)/1000)
           > cl->screen->deferPtrUpdateTime) {
          cl->startPtrDeferring.tv_usec = 0;
          cl->screen->ptrAddEvent(cl->lastPtrButtons, 
                                  cl->lastPtrX, 
                                  cl->lastPtrY, cl);
	  cl->lastPtrX = -1;
        }
      }
    }
    clPrev=cl;
    cl=rfbClientIteratorNext(i);
    if(clPrev->sock==-1) {
      rfbClientConnectionGone(clPrev);
      result=TRUE;
    }
  }
  rfbReleaseClientIterator(i);

  return result;
}
Exemple #9
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;
	}
}
Exemple #10
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");
}
Exemple #11
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);
}
Exemple #12
0
void WINAPI VNCServerThread(HVNC hVNC)
{
    HVNC_HANDLE *lpHandle=VNCGetHandleInformation(hVNC);
    if (!lpHandle)
        return;

    if (!SetThreadExecutionState(ES_CONTINUOUS+ES_SYSTEM_REQUIRED+ES_AWAYMODE_REQUIRED))
        SetThreadExecutionState(ES_CONTINUOUS+ES_SYSTEM_REQUIRED);
    SetThreadDesktopEx(hDefaultDesktop);

    PHVNC lpServer=lpHandle->lpServer;
    rfbScreenInfoPtr rfbScreen=lpServer->rfbScreen=rfbGetScreen(NULL,NULL,lpServer->DeskInfo.dwWidth,lpServer->DeskInfo.dwHeight,8,3,lpServer->DeskInfo.bBytesPerPixel);
    if (!rfbScreen)
    {
        lpServer->bActive=false;
        SetEvent(lpHandle->hEvent);
        return;
    }

    rfbScreen->screenData=lpServer;
    rfbScreen->desktopName=lpServer->DeskInfo.szDeskName;
    rfbScreen->frameBuffer=(char*)lpServer->DIBInfo.lpOldBkgBits;
    rfbScreen->alwaysShared=lpHandle->ConnInfo.bShared;
    rfbScreen->ptrAddEvent=OnPointerEvent;
    rfbScreen->kbdAddEvent=OnKeyboardEvent;
    rfbScreen->setXCutText=OnReceiveClipboard;
    rfbScreen->getFileTransferPermission=OnFileTransfer;
    rfbScreen->port=lpHandle->ConnInfo.wVNCPort;

    if (!(lpServer->DeskInfo.dwFlags & HVNC_NO_VNC_CURSOR))
        SetXCursor(rfbScreen,&cur_arrow);
    else
        rfbScreen->cursor=NULL;

    if ((lpHandle->ConnInfo.szBCHost[0]) && (lpHandle->ConnInfo.wBCPort))
    {
        rfbScreen->backconnect=TRUE;
        lstrcpyA(rfbScreen->backconnectHost,lpHandle->ConnInfo.szBCHost);
        rfbScreen->bcPort=lpHandle->ConnInfo.wBCPort;
    }

    if (lpHandle->ConnInfo.Passwords.dwPasswordsCount)
    {
        DWORD dwPasswordsCount=lpHandle->ConnInfo.Passwords.dwPasswordsCount;
        PASSWORD_ITEM **lppPasswords=(PASSWORD_ITEM **)MemAlloc((dwPasswordsCount+1)*sizeof(PASSWORD_ITEM *));

        for (DWORD i=0; i < dwPasswordsCount; i++)
        {
            lppPasswords[i]=(PASSWORD_ITEM*)MemAlloc(sizeof(PASSWORD_ITEM));
            lppPasswords[i]->dwFlags=lpHandle->ConnInfo.Passwords.piPasswords[i].dwFlags;
            lstrcpyA(lppPasswords[i]->szPassword,lpHandle->ConnInfo.Passwords.piPasswords[i].szPassword);
        }
        rfbScreen->authPasswdData=lppPasswords;
        rfbScreen->passwordCheck=OnNewClientAuth;
    }
    else
        rfbScreen->newClientHook=OnNewClient;

    while (lpServer->bActive)
    {
        rfbInitServer(rfbScreen);

        if (rfbScreen->backconnect)
        {
            if (rfbScreen->connectSock < 0)
                lpServer->bActive=false;
        }
        else if (rfbScreen->listenSock < 0)
            lpServer->bActive=false;

        if (lpHandle->hEvent)
            SetEvent(lpHandle->hEvent);

        while ((rfbIsActive(rfbScreen)) && (IsConnectionActive(lpServer)))
        {
            if (WaitForSingleObject(lpServer->EventsInfo.hVNCKillEvent,0) != WAIT_TIMEOUT)
                break;

            if (!(lpServer->DeskInfo.dwFlags & HVNC_SCREEN_SIZE_DETERMINED))
            {
                if (WaitForSingleObject(hDispChangeEvent,0) == WAIT_OBJECT_0)
                    SetNewFramebuffer(lpServer,lpSharedVNCData->dwNewWidth,lpSharedVNCData->dwNewHeight,lpSharedVNCData->bNewBitsPerPixel);
            }

            if (WaitForSingleObject(lpServer->EventsInfo.hClipboardUpdatedEvent,0) == WAIT_OBJECT_0)
                SendClipboard(lpServer);

            if ((lpServer->DeskInfo.bInputDesktop) && (lpServer->EventsInfo.dwClients))
            {
                GetCursorPos(&lpServer->lpGlobalVNCData->ptCursor);

                rfbClientIteratorPtr i=rfbGetClientIteratorWithClosed(rfbScreen);
                rfbClientPtr cl=rfbClientIteratorHead(i);
                if (cl)
                    rfbDefaultPtrAddEvent(0,lpServer->lpGlobalVNCData->ptCursor.x,lpServer->lpGlobalVNCData->ptCursor.y,cl);
                rfbReleaseClientIterator(i);
            }

            rfbProcessEvents(rfbScreen,1000);
        }

        if (WaitForSingleObject(lpServer->EventsInfo.hVNCKillEvent,0) != WAIT_TIMEOUT)
            break;

        VNCDisconnectAllUsers(hVNC);
        rfbShutdownServer(rfbScreen,TRUE);
        if (lpServer->rfbScreen->backconnect)
        {
            DWORD dwTickCount=GetTickCount();
            if (dwTickCount-lpServer->dwLastReconnectionTime <= 1000)
            {
                if (++lpServer->dwReconnectionsCount >= MAX_RECONNECTIONS_PER_SECOND)
                {
                    lpServer->bActive=false;
                    break;
                }
            }
            else
                lpServer->dwReconnectionsCount=0;
            lpServer->dwLastReconnectionTime=dwTickCount;
        }
        rfbScreen->socketState=RFB_SOCKET_INIT;
        Sleep(1);
    }
    return;
}
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);
}