diff options
Diffstat (limited to 'rfbserver.c')
-rw-r--r-- | rfbserver.c | 171 |
1 files changed, 93 insertions, 78 deletions
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); } |