From 05c8f2d4840e8e4d0166b176b8c88bfdfffcce91 Mon Sep 17 00:00:00 2001 From: dscho Date: Wed, 3 Oct 2001 02:11:59 +0000 Subject: [PATCH] upgraded to TridiaVNC 1.2.1 --- CHANGES | 8 +++-- Makefile | 2 +- TODO | 14 ++++----- main.c | 8 +++-- rfb.h | 5 +++- rfbserver.c | 44 +++++++++++++++++++-------- sockets.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++----- stats.c | 4 +++ tight.c | 77 +++++++++++++++++++++++++++++++++--------------- 9 files changed, 190 insertions(+), 57 deletions(-) diff --git a/CHANGES b/CHANGES index d9ed9c8..ccf5ee5 100644 --- a/CHANGES +++ b/CHANGES @@ -1,11 +1,13 @@ 0.2 - cursors are supported + source is now equivalent to TridiaVNC 1.2.1 + pthreads now work (use the iterators!) + cursors are supported (rfbSetCursor automatically undraws cursor) support for 3 bytes/pixel (slow!) server side colourmap support fixed rfbCloseClient not to close the connection (pthreads!) - pthreads now work + this is done lazily (and with proper signalling). cleaned up mac.c (from original OSXvnc); now compiles (untested!) - compiles cleanly on Linux, IRIX, BSD, Apple + compiles cleanly on Linux, IRIX, BSD, Apple (Darwin) fixed prototypes 0.1 rewrote API to use pseudo-methods instead of required functions. diff --git a/Makefile b/Makefile index 5c92c7a..c456673 100644 --- a/Makefile +++ b/Makefile @@ -65,7 +65,7 @@ sratest.o: sraRegion.c blooptest: blooptest.o libvncserver.a $(CC) -o blooptest blooptest.o $(LIBS) -blooptest.o: example.c +blooptest.o: example.c rfb.h $(CC) $(CFLAGS) -DBACKGROUND_LOOP_TEST -c -o blooptest.o example.c pnmshow24: pnmshow24.o libvncserver.a diff --git a/TODO b/TODO index 904a5fe..17ffe48 100644 --- a/TODO +++ b/TODO @@ -2,18 +2,16 @@ immediate: ---------- fix bug in http (java) client with big endian server: byte swapping is broken -update to newest TridiaVNC version. +udp +documentation + perhaps the option (or just hint) not to mark very tiny regions as + modified, because that is inefficient for the encodings. +optionally dont draw rich cursors as xcursors later: ------ -udp -documentation -optionally dont draw rich cursors as xcursors autoconf? at least Sun Solaris and Windows compilation -perhaps the option (or just hint) not to mark very tiny regions as modified, - because that is inefficient for the encodings. -rfbConnect, ConnectToTcpAddr CORBA cursor "smears" sometimes when not using cursor encoding (seems to be gone now; haven't debugged properly, though) @@ -21,6 +19,8 @@ cursor "smears" sometimes when not using cursor encoding done: ----- +.rfbConnect, ConnectToTcpAddr +.update to newest TridiaVNC version (1.2.1). .adapt rdp2vnc (rdesktop) .pthreads concept: How to iterate over rfbClientPtr's? So that it can be either called from rfbProcessEvents (which locks the list mutex) diff --git a/main.c b/main.c index 7412b30..7362e4d 100644 --- a/main.c +++ b/main.c @@ -48,7 +48,7 @@ rfbLog(char *format, ...) char buf[256]; time_t log_clock; - IF_PTHREADS(pthread_mutex_lock(&logMutex)); + IF_PTHREADS(LOCK(logMutex)); va_start(args, format); time(&log_clock); @@ -59,7 +59,7 @@ rfbLog(char *format, ...) fflush(stderr); va_end(args); - IF_PTHREADS(pthread_mutex_unlock(&logMutex)); + IF_PTHREADS(UNLOCK(logMutex)); } void rfbLogPerror(char *str) @@ -314,6 +314,7 @@ rfbScreenInfoPtr rfbGetScreen(int argc,char** argv, if(width&3) fprintf(stderr,"WARNING: Width (%d) is not a multiple of 4. VncViewer has problems with that.\n",width); + rfbScreen->rfbClientHead=0; rfbScreen->rfbPort=5900; rfbScreen->socketInitDone=FALSE; @@ -323,6 +324,7 @@ rfbScreenInfoPtr rfbGetScreen(int argc,char** argv, rfbScreen->udpSock=-1; rfbScreen->udpSockConnected=FALSE; rfbScreen->udpPort=0; + rfbScreen->udpClient=0; rfbScreen->maxFd=0; rfbScreen->rfbListenSock=-1; @@ -419,6 +421,7 @@ void rfbInitServer(rfbScreenInfoPtr rfbScreen) { rfbInitSockets(rfbScreen); httpInitSockets(rfbScreen); + INIT_MUTEX(logMutex); } void @@ -451,7 +454,6 @@ void rfbRunEventLoop(rfbScreenInfoPtr rfbScreen, long usec, Bool runInBackground #ifdef HAVE_PTHREADS pthread_t listener_thread; - pthread_mutex_init(&logMutex, NULL); pthread_create(&listener_thread, NULL, listenerRun, rfbScreen); return; #else diff --git a/rfb.h b/rfb.h index efb69d2..e67e683 100644 --- a/rfb.h +++ b/rfb.h @@ -221,6 +221,7 @@ typedef struct int rfbListenSock; int udpPort; int udpSock; + struct rfbClientRec* udpClient; Bool udpSockConnected; struct sockaddr_in udpRemoteAddr; Bool inetdInitDone; @@ -517,6 +518,8 @@ extern void rfbCloseClient(rfbClientPtr cl); extern int ReadExact(rfbClientPtr cl, char *buf, int len); extern int WriteExact(rfbClientPtr cl, char *buf, int len); extern void rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec); +extern int rfbConnect(rfbScreenInfoPtr rfbScreen, char* host, int port); +extern int ConnectToTcpAddr(char* host, int port); extern int ListenOnTCPPort(int port); extern int ListenOnUDPPort(int port); @@ -536,7 +539,7 @@ extern void rfbReleaseClientIterator(rfbClientIteratorPtr iterator); extern void rfbNewClientConnection(rfbScreenInfoPtr rfbScreen,int sock); extern rfbClientPtr rfbNewClient(rfbScreenInfoPtr rfbScreen,int sock); -extern rfbClientPtr rfbReverseConnection(char *host, int port); +extern rfbClientPtr rfbReverseConnection(rfbScreenInfoPtr rfbScreen,char *host, int port); extern void rfbClientConnectionGone(rfbClientPtr cl); extern void rfbProcessClientMessage(rfbClientPtr cl); extern void rfbClientConnFailed(rfbClientPtr cl, char *reason); diff --git a/rfbserver.c b/rfbserver.c index 930a9ed..f43ceac 100644 --- a/rfbserver.c +++ b/rfbserver.c @@ -34,6 +34,10 @@ #include #include +#ifdef CORBA +#include +#endif + rfbClientPtr pointerClient = NULL; /* Mutex for pointer events */ static void rfbProcessClientProtocolVersion(rfbClientPtr cl); @@ -124,6 +128,10 @@ rfbNewClientConnection(rfbScreen,sock) rfbClientPtr cl; cl = rfbNewClient(rfbScreen,sock); +#ifdef CORBA + if(cl!=NULL) + newConnection(cl, (KEYBOARD_DEVICE|POINTER_DEVICE),1,1,1); +#endif } @@ -133,27 +141,24 @@ rfbNewClientConnection(rfbScreen,sock) */ rfbClientPtr -rfbReverseConnection(host, port) +rfbReverseConnection(rfbScreen,host, port) + rfbScreenInfoPtr rfbScreen; char *host; int port; { - return NULL; - -#ifdef NOT_YET int sock; rfbClientPtr cl; - if ((sock = rfbConnect(host, port)) < 0) + if ((sock = rfbConnect(rfbScreen, host, port)) < 0) return (rfbClientPtr)NULL; - cl = rfbNewClient(sock); + cl = rfbNewClient(rfbScreen, sock); if (cl) { cl->reverseConnection = TRUE; } return cl; -#endif } @@ -189,6 +194,8 @@ rfbNewClient(rfbScreen,sock) cl->host = strdup(inet_ntoa(addr.sin_addr)); INIT_MUTEX(cl->outputMutex); + INIT_MUTEX(cl->refCountMutex); + INIT_COND(cl->deleteCond); cl->state = RFB_PROTOCOL_VERSION; @@ -323,6 +330,10 @@ rfbClientConnectionGone(cl) LOCK(cl->outputMutex); TINI_MUTEX(cl->outputMutex); +#ifdef CORBA + destroyConnection(cl); +#endif + rfbPrintStats(cl); xfree(cl); @@ -977,8 +988,10 @@ rfbSendFramebufferUpdate(cl, givenUpdateRegion) if (sendCursorShape) { cl->cursorWasChanged = FALSE; - if (!rfbSendCursorShape(cl)) + if (!rfbSendCursorShape(cl)) { + sraRgnDestroy(updateRegion); return FALSE; + } } if (!sraRgnEmpty(updateCopyRegion)) { @@ -1003,21 +1016,25 @@ rfbSendFramebufferUpdate(cl, givenUpdateRegion) switch (cl->preferredEncoding) { case rfbEncodingRaw: if (!rfbSendRectEncodingRaw(cl, x, y, w, h)) { + sraRgnDestroy(updateRegion); return FALSE; } break; case rfbEncodingRRE: if (!rfbSendRectEncodingRRE(cl, x, y, w, h)) { + sraRgnDestroy(updateRegion); return FALSE; } break; case rfbEncodingCoRRE: if (!rfbSendRectEncodingCoRRE(cl, x, y, w, h)) { + sraRgnDestroy(updateRegion); return FALSE; } break; case rfbEncodingHextile: if (!rfbSendRectEncodingHextile(cl, x, y, w, h)) { + sraRgnDestroy(updateRegion); return FALSE; } break; @@ -1038,11 +1055,14 @@ rfbSendFramebufferUpdate(cl, givenUpdateRegion) if ( nUpdateRegionRects == 0xFFFF && !rfbSendLastRectMarker(cl) ) { + sraRgnDestroy(updateRegion); return FALSE; } - if (!rfbSendUpdateBuf(cl)) + if (!rfbSendUpdateBuf(cl)) { + sraRgnDestroy(updateRegion); return FALSE; + } if(cursorWasDrawn != cl->screen->cursorIsDrawn) { if(cursorWasDrawn) @@ -1051,6 +1071,7 @@ rfbSendFramebufferUpdate(cl, givenUpdateRegion) rfbUndrawCursor(cl); } + sraRgnDestroy(updateRegion); return TRUE; } @@ -1315,7 +1336,6 @@ rfbSendServerCutText(rfbScreenInfoPtr rfbScreen,char *str, int len) rfbServerCutTextMsg sct; rfbClientIteratorPtr iterator; - /* XXX bad-- writing with client list lock held */ iterator = rfbGetClientIterator(rfbScreen); while ((cl = rfbClientIteratorNext(iterator)) != NULL) { sct.type = rfbServerCutText; @@ -1334,8 +1354,6 @@ rfbSendServerCutText(rfbScreenInfoPtr rfbScreen,char *str, int len) rfbReleaseClientIterator(iterator); } -unsigned char ptrAcceleration = 50; - /***************************************************************************** * * UDP can be used for keyboard and pointer events when the underlying @@ -1344,6 +1362,8 @@ unsigned char ptrAcceleration = 50; * packets (such as 100s of pen readings per second!). */ +unsigned char ptrAcceleration = 50; + void rfbNewUDPConnection(rfbScreen,sock) rfbScreenInfoPtr rfbScreen; diff --git a/sockets.c b/sockets.c index ef83269..3882147 100644 --- a/sockets.c +++ b/sockets.c @@ -56,7 +56,6 @@ struct timeval #include #include #include -#include #include #include "rfb.h" @@ -182,7 +181,6 @@ rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec) return; } - fprintf(stderr,"\n"); rfbLog("Got connection from client %s\n", inet_ntoa(addr.sin_addr)); FD_SET(sock, &(rfbScreen->allFds)); @@ -224,8 +222,8 @@ rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec) rfbNewUDPConnection(rfbScreen,rfbScreen->udpSock); } - //TODO: UDP also needs a client - //rfbProcessUDPInput(rfbScreen,rfbScreen->udpSock); + /* TODO: UDP also needs a client + rfbProcessUDPInput(rfbScreen,rfbScreen->udpSock); */ } FD_CLR(rfbScreen->udpSock, &fds); @@ -263,6 +261,47 @@ rfbCloseClient(cl) } +/* + * rfbConnect is called to make a connection out to a given TCP address. + */ + +int +rfbConnect(rfbScreen, host, port) + rfbScreenInfoPtr rfbScreen; + char *host; + int port; +{ + int sock; + int one = 1; + + rfbLog("Making connection to client on host %s port %d\n", + host,port); + + if ((sock = ConnectToTcpAddr(host, port)) < 0) { + rfbLogPerror("connection failed"); + return -1; + } + + if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) { + rfbLogPerror("fcntl failed"); + close(sock); + return -1; + } + + if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, + (char *)&one, sizeof(one)) < 0) { + rfbLogPerror("setsockopt failed"); + close(sock); + return -1; + } + + /* AddEnabledDevice(sock); */ + FD_SET(sock, &rfbScreen->allFds); + rfbScreen->maxFd = max(sock,rfbScreen->maxFd); + + return sock; +} + /* * ReadExact reads an exact number of bytes from a client. Returns 1 if * those bytes have been read, 0 if the other end has closed, or -1 if an error @@ -385,7 +424,6 @@ WriteExact(cl, buf, len) return 1; } - int ListenOnTCPPort(port) int port; @@ -396,7 +434,7 @@ ListenOnTCPPort(port) addr.sin_family = AF_INET; addr.sin_port = htons(port); - //addr.sin_addr.s_addr = interface.s_addr; + /* addr.sin_addr.s_addr = interface.s_addr; */ addr.sin_addr.s_addr = INADDR_ANY; if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { @@ -419,6 +457,39 @@ ListenOnTCPPort(port) return sock; } +int +ConnectToTcpAddr(host, port) + char *host; + int port; +{ + struct hostent *hp; + int sock; + struct sockaddr_in addr; + + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + + if ((addr.sin_addr.s_addr = inet_addr(host)) == -1) + { + if (!(hp = gethostbyname(host))) { + errno = EINVAL; + return -1; + } + addr.sin_addr.s_addr = *(unsigned long *)hp->h_addr; + } + + if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + return -1; + } + + if (connect(sock, (struct sockaddr *)&addr, (sizeof(addr))) < 0) { + close(sock); + return -1; + } + + return sock; +} + int ListenOnUDPPort(port) int port; @@ -429,7 +500,7 @@ ListenOnUDPPort(port) addr.sin_family = AF_INET; addr.sin_port = htons(port); - //addr.sin_addr.s_addr = interface.s_addr; + /* addr.sin_addr.s_addr = interface.s_addr; */ addr.sin_addr.s_addr = INADDR_ANY; if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { diff --git a/stats.c b/stats.c index f712021..b6fcf62 100644 --- a/stats.c +++ b/stats.c @@ -69,6 +69,10 @@ rfbPrintStats(rfbClientPtr cl) totalBytesSent += cl->rfbBytesSent[i]; } + totalRectanglesSent += (cl->rfbCursorUpdatesSent + + cl->rfbLastRectMarkersSent); + totalBytesSent += (cl->rfbCursorBytesSent + cl->rfbLastRectBytesSent); + rfbLog(" framebuffer updates %d, rectangles %d, bytes %d\n", cl->rfbFramebufferUpdateMessagesSent, totalRectanglesSent, totalBytesSent); diff --git a/tight.c b/tight.c index 509a6d8..db0d382 100644 --- a/tight.c +++ b/tight.c @@ -32,6 +32,11 @@ /* Note: The following constant should not be changed. */ #define TIGHT_MIN_TO_COMPRESS 12 +/* The parameters below may be adjusted. */ +#define MIN_SPLIT_RECT_SIZE 4096 +#define MIN_SOLID_SUBRECT_SIZE 2048 +#define MAX_SPLIT_TILE_SIZE 16 + /* May be set to TRUE with "-lazytight" Xvnc option. */ Bool rfbTightDisableGradient = FALSE; @@ -53,7 +58,7 @@ typedef struct TIGHT_CONF_s { } TIGHT_CONF; static TIGHT_CONF tightConf[10] = { - { 512, 32, 6, 65536, 0, 0, 0, 0, 0, 0, 4, 20, 10000, 25000 }, + { 512, 32, 6, 65536, 0, 0, 0, 0, 0, 0, 4, 20, 10000, 23000 }, { 2048, 128, 6, 65536, 1, 1, 1, 0, 0, 0, 8, 30, 8000, 18000 }, { 6144, 256, 8, 65536, 3, 3, 2, 0, 0, 0, 24, 40, 6500, 15000 }, { 10240, 1024, 12, 65536, 5, 5, 3, 0, 0, 0, 32, 50, 5000, 12000 }, @@ -174,10 +179,6 @@ static void JpegSetDstManager(j_compress_ptr cinfo); * Tight encoding implementation. */ -#define MIN_SPLIT_RECT_SIZE 4096 -#define MIN_SOLID_SUBRECT_SIZE 2048 -#define MAX_SPLIT_TILE_SIZE 16 - int rfbNumCodedRectsTight(cl, x, y, w, h) rfbClientPtr cl; @@ -209,11 +210,15 @@ rfbSendRectEncodingTight(cl, x, y, w, h) rfbClientPtr cl; int x, y, w, h; { + int nMaxRows; CARD32 colorValue; int dx, dy, dw, dh; int x_best, y_best, w_best, h_best; char *fbptr; + compressLevel = cl->tightCompressLevel; + qualityLevel = cl->tightQualityLevel; + if ( cl->format.depth == 24 && cl->format.redMax == 0xFF && cl->format.greenMax == 0xFF && cl->format.blueMax == 0xFF ) { usePixelFormat24 = TRUE; @@ -224,7 +229,7 @@ rfbSendRectEncodingTight(cl, x, y, w, h) if (!cl->enableLastRectEncoding || w * h < MIN_SPLIT_RECT_SIZE) return SendRectSimple(cl, x, y, w, h); - /* Make sure we can write one pixel into tightBeforeBuf. */ + /* Make sure we can write at least one pixel into tightBeforeBuf. */ if (tightBeforeBufSize < 4) { tightBeforeBufSize = 4; @@ -235,10 +240,30 @@ rfbSendRectEncodingTight(cl, x, y, w, h) tightBeforeBufSize); } + /* Calculate maximum number of rows in one non-solid rectangle. */ + + { + int maxRectSize, maxRectWidth, nMaxWidth; + + maxRectSize = tightConf[compressLevel].maxRectSize; + maxRectWidth = tightConf[compressLevel].maxRectWidth; + nMaxWidth = (w > maxRectWidth) ? maxRectWidth : w; + nMaxRows = maxRectSize / nMaxWidth; + } + /* Try to find large solid-color areas and send them separately. */ for (dy = y; dy < y + h; dy += MAX_SPLIT_TILE_SIZE) { + /* If a rectangle becomes too large, send its upper part now. */ + + if (dy - y >= nMaxRows) { + if (!SendRectSimple(cl, x, y, w, nMaxRows)) + return 0; + y += nMaxRows; + h -= nMaxRows; + } + dh = (dy + MAX_SPLIT_TILE_SIZE <= y + h) ? MAX_SPLIT_TILE_SIZE : (y + h - dy); @@ -462,8 +487,6 @@ SendRectSimple(cl, x, y, w, h) int dx, dy; int rw, rh; - compressLevel = cl->tightCompressLevel; - qualityLevel = cl->tightQualityLevel; maxRectSize = tightConf[compressLevel].maxRectSize; maxRectWidth = tightConf[compressLevel].maxRectWidth; @@ -516,6 +539,12 @@ SendSubrect(cl, x, y, w, h) char *fbptr; Bool success = FALSE; + /* Send pending data if there is more than 128 bytes. */ + if (cl->ublen > 128) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + if (!SendTightHeader(cl, x, y, w, h)) return FALSE; @@ -566,7 +595,7 @@ SendSubrect(cl, x, y, w, h) break; default: /* Up to 256 different colors */ - if ( paletteNumColors > 64 && + if ( paletteNumColors > 96 && qualityLevel != -1 && qualityLevel <= 3 && DetectSmoothImage(cl, &cl->format, w, h) ) { success = SendJpegRect(cl, x, y, w, h, @@ -644,7 +673,8 @@ SendMonoRect(cl, w, h) int streamId = 1; int paletteLen, dataLen; - if ( cl->ublen + 6 + 2 * cl->format.bitsPerPixel / 8 > UPDATE_BUF_SIZE ) { + if ( cl->ublen + TIGHT_MIN_TO_COMPRESS + 6 + + 2 * cl->format.bitsPerPixel / 8 > UPDATE_BUF_SIZE ) { if (!rfbSendUpdateBuf(cl)) return FALSE; } @@ -708,7 +738,8 @@ SendIndexedRect(cl, w, h) int streamId = 2; int i, entryLen; - if ( cl->ublen + 6 + paletteNumColors * cl->format.bitsPerPixel / 8 > + if ( cl->ublen + TIGHT_MIN_TO_COMPRESS + 6 + + paletteNumColors * cl->format.bitsPerPixel / 8 > UPDATE_BUF_SIZE ) { if (!rfbSendUpdateBuf(cl)) return FALSE; @@ -902,19 +933,19 @@ static Bool SendCompressedData(cl, compressedLen) } } - for (i = 0; i < compressedLen; ) { - portionLen = compressedLen - i; - if (portionLen > UPDATE_BUF_SIZE - cl->ublen) - portionLen = UPDATE_BUF_SIZE - cl->ublen; - + portionLen = UPDATE_BUF_SIZE; + for (i = 0; i < compressedLen; i += portionLen) { + if (i + portionLen > compressedLen) { + portionLen = compressedLen - i; + } + if (cl->ublen + portionLen > UPDATE_BUF_SIZE) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } memcpy(&cl->updateBuf[cl->ublen], &tightAfterBuf[i], portionLen); - cl->ublen += portionLen; - i += portionLen; - - if (!rfbSendUpdateBuf(cl)) - return FALSE; } + portionLen = UPDATE_BUF_SIZE; cl->rfbBytesSent[rfbEncodingTight] += compressedLen; return TRUE; } @@ -978,7 +1009,7 @@ FillPalette##bpp(count) \ \ c0 = data[0]; \ for (i = 1; i < count && data[i] == c0; i++); \ - if (i == count) { \ + if (i >= count) { \ paletteNumColors = 1; /* Solid rectangle */ \ return; \ } \ @@ -1000,7 +1031,7 @@ FillPalette##bpp(count) \ } else \ break; \ } \ - if (i == count) { \ + if (i >= count) { \ if (n0 > n1) { \ monoBackground = (CARD32)c0; \ monoForeground = (CARD32)c1; \