From 130ae151d118378e5765713581283728fdfb3e20 Mon Sep 17 00:00:00 2001
From: dscho <dscho>
Date: Tue, 2 Oct 2001 23:04:35 +0000
Subject: no more compile warnings, pthread final(?) fixes

---
 Makefile    |   4 +-
 TODO        |  25 ++++-----
 cursor.c    |  73 ++++++++------------------
 d3des.c     |   2 +
 main.c      |  48 ++++++++---------
 rfb.h       |  71 +++++++++++++++++++------
 rfbserver.c | 171 +++++++++++++++++++++++++++++++++---------------------------
 sockets.c   |  59 ++++-----------------
 translate.c |  11 ++--
 vncauth.c   |   1 +
 10 files changed, 227 insertions(+), 238 deletions(-)

diff --git a/Makefile b/Makefile
index 5fed831..5c92c7a 100644
--- a/Makefile
+++ b/Makefile
@@ -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!
diff --git a/TODO b/TODO
index 3790874..904a5fe 100644
--- a/TODO
+++ b/TODO
@@ -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
diff --git a/cursor.c b/cursor.c
index 90d6ad9..42afd3f 100644
--- a/cursor.c
+++ b/cursor.c
@@ -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);
 }
diff --git a/d3des.c b/d3des.c
index 8a358ce..60e6473 100644
--- a/d3des.c
+++ b/d3des.c
@@ -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 };
diff --git a/main.c b/main.c
index b709bb7..7412b30 100644
--- a/main.c
+++ b/main.c
@@ -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)
diff --git a/rfb.h b/rfb.h
index 81a165c..efb69d2 100644
--- a/rfb.h
+++ b/rfb.h
@@ -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);
 }
 
 
diff --git a/sockets.c b/sockets.c
index da5d99f..ef83269 100644
--- a/sockets.c
+++ b/sockets.c
@@ -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
diff --git a/vncauth.c b/vncauth.c
index 69f38cf..75f1cc3 100644
--- a/vncauth.c
+++ b/vncauth.c
@@ -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"
 
-- 
cgit v1.2.3

