diff options
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | TODO | 25 | ||||
-rw-r--r-- | cursor.c | 73 | ||||
-rw-r--r-- | d3des.c | 2 | ||||
-rw-r--r-- | main.c | 48 | ||||
-rw-r--r-- | rfb.h | 71 | ||||
-rw-r--r-- | rfbserver.c | 171 | ||||
-rw-r--r-- | sockets.c | 59 | ||||
-rw-r--r-- | translate.c | 11 | ||||
-rw-r--r-- | vncauth.c | 1 |
10 files changed, 227 insertions, 238 deletions
@@ -2,8 +2,8 @@ INCLUDES=-I. VNCSERVERLIB=-L. -lvncserver -L/usr/local/lib -lz -ljpeg # Uncomment these two lines to enable use of PThreads -#PTHREADDEF = -DHAVE_PTHREADS -#PTHREADLIB = -lpthread +PTHREADDEF = -DHAVE_PTHREADS +PTHREADLIB = -lpthread # Comment the following line to disable the use of 3 Bytes/Pixel. # The code for 3 Bytes/Pixel is not very efficient! @@ -2,34 +2,35 @@ immediate: ---------- fix bug in http (java) client with big endian server: byte swapping is broken -pthreads concept: How to iterate over rfbClientPtr's? So that it can be - either called from rfbProcessEvents (which locks the list mutex) - or from the main thread (where the background loop sometimes - locks the list mutex). - - cursor drawing! - - cursor setting! - - rfbMarkRectAsModified update to newest TridiaVNC version. -adapt rdp2vnc (rdesktop) later: ------ +udp +documentation optionally dont draw rich cursors as xcursors - -autoconf? at least Sun Solaris compilation +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. -udp rfbConnect, ConnectToTcpAddr CORBA -documentation cursor "smears" sometimes when not using cursor encoding (seems to be gone now; haven't debugged properly, though) done: ----- +.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) + or from the main thread (where the background loop sometimes + locks the list mutex). + - cursor drawing! + - cursor setting! + - rfbMarkRectAsModified + (did that by adding a refcount to clients secured by refCountMutex; + it also was necessary to check for cl->sock<0 in SendUpdateBuf) .translate.c: warning about non 8-bit colourmaps 16-bit colourmaps are 192k -> no use without fast net. .rfbCloseClient @@ -225,9 +225,6 @@ rfbCursorPtr rfbMakeXCursor(int width,int height,char* cursorString,char* maskSt char* cp; unsigned char bit; -#ifdef HAVE_PTHREADS - pthread_mutex_init(&cursor->mutex, NULL); -#endif cursor->width=width; cursor->height=height; //cursor->backRed=cursor->backGreen=cursor->backBlue=0xffff; @@ -275,9 +272,6 @@ char* rfbMakeMaskForXCursor(int width,int height,char* source) void rfbFreeCursor(rfbCursorPtr cursor) { if(cursor) { -#ifdef HAVE_PTHREADS - pthread_mutex_destroy(&cursor->mutex); -#endif free(cursor->source); free(cursor->mask); free(cursor); @@ -344,13 +338,9 @@ void rfbUndrawCursor(rfbClientPtr cl) int j,x1,x2,y1,y2,bpp=s->rfbServerFormat.bitsPerPixel/8, rowstride=s->paddedWidthInBytes; -#ifdef HAVE_PTHREADS - pthread_mutex_lock(&c->mutex); -#endif + LOCK(cl->screen->cursorMutex); if(!s->cursorIsDrawn) { -#ifdef HAVE_PTHREADS - pthread_mutex_unlock(&c->mutex); -#endif + UNLOCK(cl->screen->cursorMutex); return; } @@ -360,9 +350,7 @@ void rfbUndrawCursor(rfbClientPtr cl) if(x1<0) x1=0; if(x2>=s->width) x2=s->width-1; x2-=x1; if(x2<=0) { -#ifdef HAVE_PTHREADS - pthread_mutex_unlock(&c->mutex); -#endif + UNLOCK(cl->screen->cursorMutex); return; } y1=s->cursorY-c->yhot; @@ -370,9 +358,7 @@ void rfbUndrawCursor(rfbClientPtr cl) if(y1<0) y1=0; if(y2>=s->height) y2=s->height-1; y2-=y1; if(y2<=0) { -#ifdef HAVE_PTHREADS - pthread_mutex_unlock(&c->mutex); -#endif + UNLOCK(cl->screen->cursorMutex); return; } for(j=0;j<y2;j++) @@ -382,9 +368,7 @@ void rfbUndrawCursor(rfbClientPtr cl) rfbMarkRectAsModified(s,x1,y1,x1+x2,y1+y2); s->cursorIsDrawn = FALSE; -#ifdef HAVE_PTHREADS - pthread_mutex_unlock(&c->mutex); -#endif + UNLOCK(cl->screen->cursorMutex); } void rfbDrawCursor(rfbClientPtr cl) @@ -395,14 +379,10 @@ void rfbDrawCursor(rfbClientPtr cl) rowstride=s->paddedWidthInBytes, bufSize,w; if(!c) return; -#ifdef HAVE_PTHREADS - pthread_mutex_lock(&c->mutex); -#endif + LOCK(cl->screen->cursorMutex); if(s->cursorIsDrawn) { /* is already drawn */ -#ifdef HAVE_PTHREADS - pthread_mutex_unlock(&c->mutex); -#endif + UNLOCK(cl->screen->cursorMutex); return; } bufSize=c->width*c->height*bpp; @@ -420,9 +400,7 @@ void rfbDrawCursor(rfbClientPtr cl) if(x1<0) { i1=-x1; x1=0; } if(x2>=s->width) x2=s->width-1; x2-=x1; if(x2<=0) { -#ifdef HAVE_PTHREADS - pthread_mutex_unlock(&c->mutex); -#endif + UNLOCK(cl->screen->cursorMutex); return; /* nothing to do */ } y1=s->cursorY-c->yhot; @@ -430,9 +408,7 @@ void rfbDrawCursor(rfbClientPtr cl) if(y1<0) { j1=-y1; y1=0; } if(y2>=s->height) y2=s->height-1; y2-=y1; if(y2<=0) { -#ifdef HAVE_PTHREADS - pthread_mutex_unlock(&c->mutex); -#endif + UNLOCK(cl->screen->cursorMutex); return; /* nothing to do */ } for(j=0;j<y2;j++) @@ -452,9 +428,7 @@ void rfbDrawCursor(rfbClientPtr cl) rfbMarkRectAsModified(s,x1,y1,x1+x2,y1+y2); s->cursorIsDrawn = TRUE; -#ifdef HAVE_PTHREADS - pthread_mutex_unlock(&c->mutex); -#endif + UNLOCK(cl->screen->cursorMutex); } /* for debugging */ @@ -475,26 +449,21 @@ void rfbPrintXCursor(rfbCursorPtr cursor) extern void rfbSetCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr c,Bool freeOld) { + rfbClientIteratorPtr i = rfbGetClientIterator(rfbScreen); rfbClientPtr cl; -#ifdef HAVE_PTHREADS - pthread_mutex_lock(rfbScreen->cursor->mutex); -#endif - for(cl=rfbScreen->rfbClientHead;cl;cl=cl->next) - if(cl->sock>=0) { -#ifdef HAVE_PTHREADS - pthread_mutex_lock(cl->updateMutex); -#endif - rfbUndrawCursor(cl); -#ifdef HAVE_PTHREADS - pthread_mutex_unlock(cl->updateMutex); -#endif + + LOCK(rfbScreen->cursorMutex); + + while((cl=rfbClientIteratorNext(i))) { + LOCK(cl->updateMutex); + rfbUndrawCursor(cl); + UNLOCK(cl->updateMutex); } -#ifdef HAVE_PTHREADS - pthread_mutex_unlock(rfbScreen->cursor->mutex); -#endif - + if(freeOld && rfbScreen->cursor) rfbFreeCursor(rfbScreen->cursor); rfbScreen->cursor = c; + + UNLOCK(rfbScreen->cursorMutex); } @@ -34,12 +34,14 @@ static void desfunc(unsigned long *, unsigned long *); static void cookey(unsigned long *); static unsigned long KnL[32] = { 0L }; +/* static unsigned long KnR[32] = { 0L }; static unsigned long Kn3[32] = { 0L }; static unsigned char Df_Key[24] = { 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, 0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10, 0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 }; +*/ static unsigned short bytebit[8] = { 01, 02, 04, 010, 020, 040, 0100, 0200 }; @@ -75,14 +75,10 @@ void rfbMarkRegionAsModified(rfbScreenInfoPtr rfbScreen,sraRegionPtr modRegion) iterator=rfbGetClientIterator(rfbScreen); while((cl=rfbClientIteratorNext(iterator))) { -#ifdef HAVE_PTHREADS - pthread_mutex_lock(&cl->updateMutex); -#endif + LOCK(cl->updateMutex); sraRgnOr(cl->modifiedRegion,modRegion); -#ifdef HAVE_PTHREADS - pthread_cond_signal(&cl->updateCond); - pthread_mutex_unlock(&cl->updateMutex); -#endif + SIGNAL(cl->updateCond); + UNLOCK(cl->updateMutex); } rfbReleaseClientIterator(iterator); @@ -120,11 +116,11 @@ clientOutput(void *data) while (1) { haveUpdate = false; - pthread_mutex_lock(&cl->updateMutex); + LOCK(cl->updateMutex); while (!haveUpdate) { if (cl->sock == -1) { /* Client has disconnected. */ - pthread_mutex_unlock(&cl->updateMutex); + UNLOCK(cl->updateMutex); return NULL; } updateRegion = sraRgnCreateRgn(cl->modifiedRegion); @@ -132,24 +128,24 @@ clientOutput(void *data) sraRgnDestroy(updateRegion); if (!haveUpdate) { - pthread_cond_wait(&cl->updateCond, &cl->updateMutex); + WAIT(cl->updateCond, cl->updateMutex); } } /* OK, now, to save bandwidth, wait a little while for more updates to come along. */ - pthread_mutex_unlock(&cl->updateMutex); + UNLOCK(cl->updateMutex); usleep(rfbDeferUpdateTime * 1000); /* Now, get the region we're going to update, and remove it from cl->modifiedRegion _before_ we send the update. That way, if anything that overlaps the region we're sending is updated, we'll be sure to do another update later. */ - pthread_mutex_lock(&cl->updateMutex); + LOCK(cl->updateMutex); updateRegion = sraRgnCreateRgn(cl->modifiedRegion); sraRgnAnd(updateRegion,cl->requestedRegion); sraRgnSubtract(cl->modifiedRegion,updateRegion); - pthread_mutex_unlock(&cl->updateMutex); + UNLOCK(cl->updateMutex); /* Now actually send the update. */ rfbSendFramebufferUpdate(cl, updateRegion); @@ -176,10 +172,10 @@ clientInput(void *data) } /* Get rid of the output thread. */ - pthread_mutex_lock(&cl->updateMutex); - pthread_cond_signal(&cl->updateCond); - pthread_mutex_unlock(&cl->updateMutex); - pthread_join(output_thread, NULL); + LOCK(cl->updateMutex); + SIGNAL(cl->updateCond); + UNLOCK(cl->updateMutex); + IF_PTHREADS(pthread_join(output_thread, NULL)); rfbClientConnectionGone(cl); @@ -389,6 +385,7 @@ rfbScreenInfoPtr rfbGetScreen(int argc,char** argv, rfbScreen->dontSendFramebufferUpdate = FALSE; rfbScreen->cursorX=rfbScreen->cursorY=rfbScreen->underCursorBufferLen=0; rfbScreen->underCursorBuffer=NULL; + //INIT_MUTEX(rfbScreen->cursorMutex); /* proc's and hook's */ @@ -410,6 +407,11 @@ rfbScreenInfoPtr rfbGetScreen(int argc,char** argv, void rfbScreenCleanup(rfbScreenInfoPtr rfbScreen) { /* TODO */ + if(rfbScreen->frameBuffer) + free(rfbScreen->frameBuffer); + if(rfbScreen->colourMap.data.bytes) + free(rfbScreen->colourMap.data.bytes); + TINI_MUTEX(rfbScreen->cursorMutex); free(rfbScreen); } @@ -422,7 +424,8 @@ void rfbInitServer(rfbScreenInfoPtr rfbScreen) void rfbProcessEvents(rfbScreenInfoPtr rfbScreen,long usec) { - rfbClientPtr cl,cl_next; + rfbClientIteratorPtr i; + rfbClientPtr cl; rfbCheckFds(rfbScreen,usec); httpCheckFds(rfbScreen); @@ -430,17 +433,14 @@ rfbProcessEvents(rfbScreenInfoPtr rfbScreen,long usec) corbaCheckFds(rfbScreen); #endif - /* this needn't be thread safe: - you use rfbRunEventLoop(..,TRUE) for pthreads. */ - cl=rfbScreen->rfbClientHead; - while(cl) { - cl_next=cl->next; + i = rfbGetClientIterator(rfbScreen); + while((cl=rfbClientIteratorNext(i))) { if(cl->sock>=0 && FB_UPDATE_PENDING(cl)) rfbSendFramebufferUpdate(cl,cl->modifiedRegion); if(cl->sock==-1) rfbClientConnectionGone(cl); - cl=cl_next; } + rfbReleaseClientIterator(i); } void rfbRunEventLoop(rfbScreenInfoPtr rfbScreen, long usec, Bool runInBackground) @@ -52,15 +52,6 @@ int max(int,int); #include <rfbproto.h> -#ifdef HAVE_PTHREADS -#include <pthread.h> -#define IF_PTHREADS(x) (x) -#else -#define IF_PTHREADS(x) -#endif - - - #ifdef __linux__ #include <endian.h> #else @@ -84,6 +75,47 @@ int max(int,int); #include <netinet/in.h> +#ifdef HAVE_PTHREADS +#include <pthread.h> +#if 0 +#define LOCK(mutex) fprintf(stderr,"%s:%d LOCK(%s)\n",__FILE__,__LINE__,#mutex) +#define UNLOCK(mutex) fprintf(stderr,"%s:%d UNLOCK(%s)\n",__FILE__,__LINE__,#mutex) +#define MUTEX(mutex) +#define INIT_MUTEX(mutex) fprintf(stderr,"%s:%d INIT_MUTEX(%s)\n",__FILE__,__LINE__,#mutex) +#define TINI_MUTEX(mutex) fprintf(stderr,"%s:%d TINI_MUTEX(%s)\n",__FILE__,__LINE__,#mutex) +#define SIGNAL(cond) fprintf(stderr,"%s:%d SIGNAL(%s)\n",__FILE__,__LINE__,#cond) +#define WAIT(cond,mutex) fprintf(stderr,"%s:%d WAIT(%s,%s)\n",__FILE__,__LINE__,#cond,#mutex) +#define COND(cond) +#define INIT_COND(cond) fprintf(stderr,"%s:%d INIT_COND(%s)\n",__FILE__,__LINE__,#cond) +#define TINI_COND(cond) fprintf(stderr,"%s:%d TINI_COND(%s)\n",__FILE__,__LINE__,#cond) +#define IF_PTHREAD(x) +#else +#define LOCK(mutex) pthread_mutex_lock(&(mutex)) +#define UNLOCK(mutex) pthread_mutex_unlock(&(mutex)) +#define MUTEX(mutex) pthread_mutex_t (mutex) +#define INIT_MUTEX(mutex) pthread_mutex_init(&(mutex),NULL) +#define TINI_MUTEX(mutex) pthread_mutex_destroy(&(mutex)) +#define SIGNAL(cond) pthread_cond_signal(&(cond)) +#define WAIT(cond,mutex) pthread_cond_wait(&(cond),&(mutex)) +#define COND(cond) pthread_cond_t (cond) +#define INIT_COND(cond) pthread_cond_init(&(cond),NULL) +#define TINI_COND(cond) pthread_cond_destroy(&(cond)) +#define IF_PTHREADS(x) x +#endif +#else +#define LOCK(mutex) +#define UNLOCK(mutex) +#define MUTEX(mutex) +#define INIT_MUTEX(mutex) +#define TINI_MUTEX(mutex) +#define SIGNAL(cond) this_is_unsupported +#define WAIT(cond,mutex) this_is_unsupported +#define COND(cond) +#define INIT_COND(cond) +#define TINI_COND(cond) +#define IF_PTHREADS(x) +#endif + #define MAX_ENCODINGS 10 struct rfbClientRec; @@ -210,6 +242,7 @@ typedef struct Bool rfbDontDisconnect; struct rfbClientRec* rfbClientHead; struct rfbCursor* cursor; + MUTEX(cursorMutex); /* the following members have to be supplied by the serving process */ char* frameBuffer; @@ -273,7 +306,7 @@ typedef struct rfbClientRec { */ void* clientData; ClientGoneHookPtr clientGoneHook; - + int sock; char *host; /* Possible client states: */ @@ -324,10 +357,17 @@ typedef struct rfbClientRec { #ifdef HAVE_PTHREADS - pthread_mutex_t dontKillMutex; /* if you need a reliable clientPtr */ - pthread_mutex_t outputMutex; - pthread_mutex_t updateMutex; - pthread_cond_t updateCond; + /* whenever a client is referenced, the refCount has to be incremented + and afterwards decremented. + Use the functions rfbIncrClientRef(cl) and rfbDecrClientRef(cl); + */ + int refCount; + MUTEX(refCountMutex); + COND(deleteCond); + + MUTEX(outputMutex); + MUTEX(updateMutex); + COND(updateCond); #endif sraRegionPtr modifiedRegion; @@ -598,9 +638,6 @@ typedef struct rfbCursor { unsigned short foreRed, foreGreen, foreBlue; /* device-independent colour */ unsigned short backRed, backGreen, backBlue; /* device-independent colour */ unsigned char *richSource; /* source bytes for a rich cursor */ -#ifdef HAVE_PTHREADS - pthread_mutex_t mutex; -#endif } rfbCursor, *rfbCursorPtr; extern Bool rfbSendCursorShape(rfbClientPtr cl/*, rfbScreenInfoPtr pScreen*/); diff --git a/rfbserver.c b/rfbserver.c index c1bf69d..930a9ed 100644 --- a/rfbserver.c +++ b/rfbserver.c @@ -33,9 +33,6 @@ #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> -#ifdef HAVE_PTHREADS -#include <pthread.h> -#endif rfbClientPtr pointerClient = NULL; /* Mutex for pointer events */ @@ -43,52 +40,74 @@ static void rfbProcessClientProtocolVersion(rfbClientPtr cl); static void rfbProcessClientNormalMessage(rfbClientPtr cl); static void rfbProcessClientInitMessage(rfbClientPtr cl); +#ifdef HAVE_PTHREADS +void rfbIncrClientRef(rfbClientPtr cl) +{ + LOCK(cl->refCountMutex); + cl->refCount++; + UNLOCK(cl->refCountMutex); +} + +void rfbDecrClientRef(rfbClientPtr cl) +{ + LOCK(cl->refCountMutex); + cl->refCount--; + if(cl->refCount<=0) /* just to be sure also < 0 */ + SIGNAL(cl->deleteCond); + UNLOCK(cl->refCountMutex); +} +#endif + +MUTEX(rfbClientListMutex); struct rfbClientIterator { - rfbClientPtr next; + rfbClientPtr next; + rfbScreenInfoPtr screen; }; -#ifdef HAVE_PTHREADS -static pthread_mutex_t rfbClientListMutex; -#endif -static struct rfbClientIterator rfbClientIteratorInstance; - void rfbClientListInit(rfbScreenInfoPtr rfbScreen) { rfbScreen->rfbClientHead = NULL; -#ifdef HAVE_PTHREADS - pthread_mutex_init(&rfbClientListMutex, NULL); -#endif } rfbClientIteratorPtr rfbGetClientIterator(rfbScreenInfoPtr rfbScreen) { -#ifdef HAVE_PTHREADS - pthread_mutex_lock(&rfbClientListMutex); -#endif - rfbClientIteratorInstance.next = rfbScreen->rfbClientHead; - - return &rfbClientIteratorInstance; + rfbClientIteratorPtr i = + (rfbClientIteratorPtr)malloc(sizeof(struct rfbClientIterator)); + i->next = 0; + i->screen = rfbScreen; + return i; } rfbClientPtr -rfbClientIteratorNext(rfbClientIteratorPtr iterator) +rfbClientIteratorNext(rfbClientIteratorPtr i) { - rfbClientPtr result; - result = iterator->next; - if (result) - iterator->next = result->next; - return result; + if(i->next == 0) { + LOCK(rfbClientListMutex); + i->next = i->screen->rfbClientHead; + UNLOCK(rfbClientListMutex); + } else { + IF_PTHREADS(rfbClientPtr cl = i->next); + i->next = i->next->next; + IF_PTHREADS(rfbDecrClientRef(cl)); + } + +#ifdef HAVE_PTHREADS + while(i->next && i->next->sock<0) + i->next = i->next->next; + if(i->next) + rfbIncrClientRef(i->next); +#endif + + return i->next; } void rfbReleaseClientIterator(rfbClientIteratorPtr iterator) { -#ifdef HAVE_PTHREADS - pthread_mutex_unlock(&rfbClientListMutex); -#endif + IF_PTHREADS(if(iterator->next) rfbDecrClientRef(iterator->next)); } @@ -169,9 +188,7 @@ rfbNewClient(rfbScreen,sock) getpeername(sock, (struct sockaddr *)&addr, &addrlen); cl->host = strdup(inet_ntoa(addr.sin_addr)); -#ifdef HAVE_PTHREADS - pthread_mutex_init(&cl->outputMutex, NULL); -#endif + INIT_MUTEX(cl->outputMutex); cl->state = RFB_PROTOCOL_VERSION; @@ -189,10 +206,8 @@ rfbNewClient(rfbScreen,sock) cl->modifiedRegion = sraRgnCreateRect(0,0,rfbScreen->width,rfbScreen->height); -#ifdef HAVE_PTHREADS - pthread_mutex_init(&cl->updateMutex, NULL); - pthread_cond_init(&cl->updateCond, NULL); -#endif + INIT_MUTEX(cl->updateMutex); + INIT_COND(cl->updateCond); cl->requestedRegion = sraRgnCreate(); @@ -200,18 +215,16 @@ rfbNewClient(rfbScreen,sock) cl->translateFn = rfbTranslateNone; cl->translateLookupTable = NULL; -#ifdef HAVE_PTHREADS - pthread_mutex_lock(&rfbClientListMutex); -#endif + LOCK(rfbClientListMutex); + + cl->refCount = 0; cl->next = rfbScreen->rfbClientHead; cl->prev = NULL; if (rfbScreen->rfbClientHead) rfbScreen->rfbClientHead->prev = cl; rfbScreen->rfbClientHead = cl; -#ifdef HAVE_PTHREADS - pthread_mutex_unlock(&rfbClientListMutex); -#endif + UNLOCK(rfbClientListMutex); cl->tightCompressLevel = TIGHT_DEFAULT_COMPRESSION; cl->tightQualityLevel = -1; @@ -261,12 +274,23 @@ rfbClientConnectionGone(cl) { int i; + LOCK(rfbClientListMutex); + + if (cl->prev) + cl->prev->next = cl->next; + else + cl->screen->rfbClientHead = cl->next; + if (cl->next) + cl->next->prev = cl->prev; + #ifdef HAVE_PTHREADS - /* - pthread_mutex_lock(&cl->updateMutex); - pthread_mutex_lock(&cl->outputMutex); - */ - pthread_mutex_lock(&rfbClientListMutex); + LOCK(cl->refCountMutex); + if(cl->refCount) { + UNLOCK(cl->refCountMutex); + WAIT(cl->deleteCond,cl->refCountMutex); + } else { + UNLOCK(cl->refCountMutex); + } #endif cl->clientGoneHook(cl); @@ -287,28 +311,19 @@ rfbClientConnectionGone(cl) if (pointerClient == cl) pointerClient = NULL; - if (cl->prev) - cl->prev->next = cl->next; - else - cl->screen->rfbClientHead = cl->next; - if (cl->next) - cl->next->prev = cl->prev; - sraRgnDestroy(cl->modifiedRegion); - rfbPrintStats(cl); + UNLOCK(rfbClientListMutex); if (cl->translateLookupTable) free(cl->translateLookupTable); -#ifdef HAVE_PTHREADS - pthread_mutex_unlock(&rfbClientListMutex); -#endif + TINI_COND(cl->updateCond); + TINI_MUTEX(cl->updateMutex); -#ifdef HAVE_PTHREADS - pthread_cond_destroy(&cl->updateCond); - pthread_mutex_destroy(&cl->updateMutex); - pthread_mutex_destroy(&cl->outputMutex); -#endif + LOCK(cl->outputMutex); + TINI_MUTEX(cl->outputMutex); + + rfbPrintStats(cl); xfree(cl); } @@ -694,9 +709,7 @@ rfbProcessClientNormalMessage(cl) Swap16IfLE(msg.fur.x)+Swap16IfLE(msg.fur.w), Swap16IfLE(msg.fur.y)+Swap16IfLE(msg.fur.h)); -#ifdef HAVE_PTHREADS - pthread_mutex_lock(&cl->updateMutex); -#endif + LOCK(cl->updateMutex); sraRgnOr(cl->requestedRegion,tmpRegion); if (!cl->readyForSetColourMapEntries) { @@ -713,19 +726,16 @@ rfbProcessClientNormalMessage(cl) if (!msg.fur.incremental) { sraRgnOr(cl->modifiedRegion,tmpRegion); sraRgnSubtract(cl->copyRegion,tmpRegion); - } -#ifdef HAVE_PTHREADS - pthread_cond_signal(&cl->updateCond); - pthread_mutex_unlock(&cl->updateMutex); -#endif - - if(cl->sock>=0 && FB_UPDATE_PENDING(cl)) { - rfbSendFramebufferUpdate(cl,cl->modifiedRegion); - } + } + SIGNAL(cl->updateCond); + UNLOCK(cl->updateMutex); - sraRgnDestroy(tmpRegion); + if(cl->sock>=0 && FB_UPDATE_PENDING(cl)) { + rfbSendFramebufferUpdate(cl,cl->modifiedRegion); + } + sraRgnDestroy(tmpRegion); - return; + return; } case rfbKeyEvent: @@ -1209,6 +1219,9 @@ Bool rfbSendUpdateBuf(cl) rfbClientPtr cl; { + if(cl->sock<0) + return FALSE; + if (WriteExact(cl, cl->updateBuf, cl->ublen) < 0) { rfbLogPerror("rfbSendUpdateBuf: write"); rfbCloseClient(cl); @@ -1275,17 +1288,19 @@ rfbSendSetColourMapEntries(cl, firstColour, nColours) void rfbSendBell(rfbScreenInfoPtr rfbScreen) { - rfbClientPtr cl, nextCl; + rfbClientIteratorPtr i; + rfbClientPtr cl; rfbBellMsg b; - for (cl = rfbScreen->rfbClientHead; cl; cl = nextCl) { - nextCl = cl->next; + i = rfbGetClientIterator(rfbScreen); + while((cl=rfbClientIteratorNext(i))) { b.type = rfbBell; if (WriteExact(cl, (char *)&b, sz_rfbBellMsg) < 0) { rfbLogPerror("rfbSendBell: write"); rfbCloseClient(cl); } } + rfbReleaseClientIterator(i); } @@ -142,7 +142,7 @@ rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec) const int one = 1; int sock; rfbClientIteratorPtr i; - rfbClientPtr cl,cl_next; + rfbClientPtr cl; if (!rfbScreen->inetdInitDone && rfbScreen->inetdSock != -1) { rfbNewClientConnection(rfbScreen,rfbScreen->inetdSock); @@ -233,34 +233,12 @@ rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec) return; } - /* I know that this is horrible. But we have the following problem: - inside this loop, the IO functions access the clients via the - iterator. - So we have to lock rfbClientListMutex to fetch a reliable - rfbClientHead. Remember, a client can just go away in a multithreaded - environment. So we have to lock the next client before working with - the current. - */ i = rfbGetClientIterator(rfbScreen); - cl = rfbClientIteratorNext(i); - if(cl) { -#ifdef HAVE_PTHREADS - //pthread_mutex_lock(&cl->updateMutex); -#endif - } - rfbReleaseClientIterator(i); - - while(cl) { - cl_next = cl->next; -#ifdef HAVE_PTHREADS - //pthread_mutex_unlock(&cl->updateMutex); - //if(cl_next) - //pthread_mutex_lock(&cl_next->updateMutex); -#endif + while((cl = rfbClientIteratorNext(i))) { if (FD_ISSET(cl->sock, &fds) && FD_ISSET(cl->sock, &(rfbScreen->allFds))) rfbProcessClientMessage(cl); - cl=cl_next; } + rfbReleaseClientIterator(i); } @@ -276,17 +254,12 @@ void rfbCloseClient(cl) rfbClientPtr cl; { -#ifdef HAVE_PTHREADS - pthread_mutex_lock(&cl->updateMutex); -#endif + LOCK(cl->updateMutex); FD_CLR(cl->sock,&(cl->screen->allFds)); close(cl->sock); cl->sock = -1; -#ifdef HAVE_PTHREADS - pthread_cond_signal(&cl->updateCond); - //pthread_mutex_lock(&cl->updateMutex); - pthread_mutex_unlock(&cl->updateMutex); -#endif + SIGNAL(cl->updateCond); + UNLOCK(cl->updateMutex); } @@ -362,9 +335,7 @@ WriteExact(cl, buf, len) struct timeval tv; int totalTimeWaited = 0; -#ifdef HAVE_PTHREADS - pthread_mutex_lock(&cl->outputMutex); -#endif + LOCK(cl->outputMutex); while (len > 0) { n = write(sock, buf, len); @@ -380,9 +351,7 @@ WriteExact(cl, buf, len) } else { if (errno != EWOULDBLOCK && errno != EAGAIN) { -#ifdef HAVE_PTHREADS - pthread_mutex_unlock(&cl->outputMutex); -#endif + UNLOCK(cl->outputMutex); return n; } @@ -397,18 +366,14 @@ WriteExact(cl, buf, len) n = select(sock+1, NULL, &fds, NULL, &tv); if (n < 0) { rfbLogPerror("WriteExact: select"); -#ifdef HAVE_PTHREADS - pthread_mutex_unlock(&cl->outputMutex); -#endif + UNLOCK(cl->outputMutex); return n; } if (n == 0) { totalTimeWaited += 5000; if (totalTimeWaited >= rfbMaxClientWait) { errno = ETIMEDOUT; -#ifdef HAVE_PTHREADS - pthread_mutex_unlock(&cl->outputMutex); -#endif + UNLOCK(cl->outputMutex); return -1; } } else { @@ -416,9 +381,7 @@ WriteExact(cl, buf, len) } } } -#ifdef HAVE_PTHREADS - pthread_mutex_unlock(&cl->outputMutex); -#endif + UNLOCK(cl->outputMutex); return 1; } diff --git a/translate.c b/translate.c index 59128a5..5efc52c 100644 --- a/translate.c +++ b/translate.c @@ -449,12 +449,13 @@ rfbSetClientColourMaps(rfbScreen, firstColour, nColours) int firstColour; int nColours; { - rfbClientPtr cl, nextCl; + rfbClientIteratorPtr i; + rfbClientPtr cl; - for (cl = rfbScreen->rfbClientHead; cl; cl = nextCl) { - nextCl = cl->next; - rfbSetClientColourMap(cl, firstColour, nColours); - } + i = rfbGetClientIterator(rfbScreen); + while((cl = rfbClientIteratorNext(i))) + rfbSetClientColourMap(cl, firstColour, nColours); + rfbReleaseClientIterator(i); } static void @@ -26,6 +26,7 @@ #include <string.h> #include <sys/types.h> #include <sys/stat.h> +#include <sys/time.h> #include "rfb.h" #include "d3des.h" |