summaryrefslogtreecommitdiffstats
path: root/rfbserver.c
diff options
context:
space:
mode:
Diffstat (limited to 'rfbserver.c')
-rw-r--r--rfbserver.c171
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);
}