no more compile warnings, pthread final(?) fixes

pull/1/head
dscho 23 years ago
parent b8c6f3b188
commit 130ae151d1

@ -2,8 +2,8 @@ INCLUDES=-I.
VNCSERVERLIB=-L. -lvncserver -L/usr/local/lib -lz -ljpeg VNCSERVERLIB=-L. -lvncserver -L/usr/local/lib -lz -ljpeg
# Uncomment these two lines to enable use of PThreads # Uncomment these two lines to enable use of PThreads
#PTHREADDEF = -DHAVE_PTHREADS PTHREADDEF = -DHAVE_PTHREADS
#PTHREADLIB = -lpthread PTHREADLIB = -lpthread
# Comment the following line to disable the use of 3 Bytes/Pixel. # Comment the following line to disable the use of 3 Bytes/Pixel.
# The code for 3 Bytes/Pixel is not very efficient! # The code for 3 Bytes/Pixel is not very efficient!

25
TODO

@ -2,34 +2,35 @@ immediate:
---------- ----------
fix bug in http (java) client with big endian server: byte swapping is broken 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. update to newest TridiaVNC version.
adapt rdp2vnc (rdesktop)
later: later:
------ ------
udp
documentation
optionally dont draw rich cursors as xcursors optionally dont draw rich cursors as xcursors
autoconf? at least Sun Solaris and Windows compilation
autoconf? at least Sun Solaris compilation
perhaps the option (or just hint) not to mark very tiny regions as modified, perhaps the option (or just hint) not to mark very tiny regions as modified,
because that is inefficient for the encodings. because that is inefficient for the encodings.
udp
rfbConnect, ConnectToTcpAddr rfbConnect, ConnectToTcpAddr
CORBA CORBA
documentation
cursor "smears" sometimes when not using cursor encoding cursor "smears" sometimes when not using cursor encoding
(seems to be gone now; haven't debugged properly, though) (seems to be gone now; haven't debugged properly, though)
done: 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 .translate.c: warning about non 8-bit colourmaps
16-bit colourmaps are 192k -> no use without fast net. 16-bit colourmaps are 192k -> no use without fast net.
.rfbCloseClient .rfbCloseClient

@ -225,9 +225,6 @@ rfbCursorPtr rfbMakeXCursor(int width,int height,char* cursorString,char* maskSt
char* cp; char* cp;
unsigned char bit; unsigned char bit;
#ifdef HAVE_PTHREADS
pthread_mutex_init(&cursor->mutex, NULL);
#endif
cursor->width=width; cursor->width=width;
cursor->height=height; cursor->height=height;
//cursor->backRed=cursor->backGreen=cursor->backBlue=0xffff; //cursor->backRed=cursor->backGreen=cursor->backBlue=0xffff;
@ -275,9 +272,6 @@ char* rfbMakeMaskForXCursor(int width,int height,char* source)
void rfbFreeCursor(rfbCursorPtr cursor) void rfbFreeCursor(rfbCursorPtr cursor)
{ {
if(cursor) { if(cursor) {
#ifdef HAVE_PTHREADS
pthread_mutex_destroy(&cursor->mutex);
#endif
free(cursor->source); free(cursor->source);
free(cursor->mask); free(cursor->mask);
free(cursor); free(cursor);
@ -344,13 +338,9 @@ void rfbUndrawCursor(rfbClientPtr cl)
int j,x1,x2,y1,y2,bpp=s->rfbServerFormat.bitsPerPixel/8, int j,x1,x2,y1,y2,bpp=s->rfbServerFormat.bitsPerPixel/8,
rowstride=s->paddedWidthInBytes; rowstride=s->paddedWidthInBytes;
#ifdef HAVE_PTHREADS LOCK(cl->screen->cursorMutex);
pthread_mutex_lock(&c->mutex);
#endif
if(!s->cursorIsDrawn) { if(!s->cursorIsDrawn) {
#ifdef HAVE_PTHREADS UNLOCK(cl->screen->cursorMutex);
pthread_mutex_unlock(&c->mutex);
#endif
return; return;
} }
@ -360,9 +350,7 @@ void rfbUndrawCursor(rfbClientPtr cl)
if(x1<0) x1=0; if(x1<0) x1=0;
if(x2>=s->width) x2=s->width-1; if(x2>=s->width) x2=s->width-1;
x2-=x1; if(x2<=0) { x2-=x1; if(x2<=0) {
#ifdef HAVE_PTHREADS UNLOCK(cl->screen->cursorMutex);
pthread_mutex_unlock(&c->mutex);
#endif
return; return;
} }
y1=s->cursorY-c->yhot; y1=s->cursorY-c->yhot;
@ -370,9 +358,7 @@ void rfbUndrawCursor(rfbClientPtr cl)
if(y1<0) y1=0; if(y1<0) y1=0;
if(y2>=s->height) y2=s->height-1; if(y2>=s->height) y2=s->height-1;
y2-=y1; if(y2<=0) { y2-=y1; if(y2<=0) {
#ifdef HAVE_PTHREADS UNLOCK(cl->screen->cursorMutex);
pthread_mutex_unlock(&c->mutex);
#endif
return; return;
} }
for(j=0;j<y2;j++) for(j=0;j<y2;j++)
@ -382,9 +368,7 @@ void rfbUndrawCursor(rfbClientPtr cl)
rfbMarkRectAsModified(s,x1,y1,x1+x2,y1+y2); rfbMarkRectAsModified(s,x1,y1,x1+x2,y1+y2);
s->cursorIsDrawn = FALSE; s->cursorIsDrawn = FALSE;
#ifdef HAVE_PTHREADS UNLOCK(cl->screen->cursorMutex);
pthread_mutex_unlock(&c->mutex);
#endif
} }
void rfbDrawCursor(rfbClientPtr cl) void rfbDrawCursor(rfbClientPtr cl)
@ -395,14 +379,10 @@ void rfbDrawCursor(rfbClientPtr cl)
rowstride=s->paddedWidthInBytes, rowstride=s->paddedWidthInBytes,
bufSize,w; bufSize,w;
if(!c) return; if(!c) return;
#ifdef HAVE_PTHREADS LOCK(cl->screen->cursorMutex);
pthread_mutex_lock(&c->mutex);
#endif
if(s->cursorIsDrawn) { if(s->cursorIsDrawn) {
/* is already drawn */ /* is already drawn */
#ifdef HAVE_PTHREADS UNLOCK(cl->screen->cursorMutex);
pthread_mutex_unlock(&c->mutex);
#endif
return; return;
} }
bufSize=c->width*c->height*bpp; bufSize=c->width*c->height*bpp;
@ -420,9 +400,7 @@ void rfbDrawCursor(rfbClientPtr cl)
if(x1<0) { i1=-x1; x1=0; } if(x1<0) { i1=-x1; x1=0; }
if(x2>=s->width) x2=s->width-1; if(x2>=s->width) x2=s->width-1;
x2-=x1; if(x2<=0) { x2-=x1; if(x2<=0) {
#ifdef HAVE_PTHREADS UNLOCK(cl->screen->cursorMutex);
pthread_mutex_unlock(&c->mutex);
#endif
return; /* nothing to do */ return; /* nothing to do */
} }
y1=s->cursorY-c->yhot; y1=s->cursorY-c->yhot;
@ -430,9 +408,7 @@ void rfbDrawCursor(rfbClientPtr cl)
if(y1<0) { j1=-y1; y1=0; } if(y1<0) { j1=-y1; y1=0; }
if(y2>=s->height) y2=s->height-1; if(y2>=s->height) y2=s->height-1;
y2-=y1; if(y2<=0) { y2-=y1; if(y2<=0) {
#ifdef HAVE_PTHREADS UNLOCK(cl->screen->cursorMutex);
pthread_mutex_unlock(&c->mutex);
#endif
return; /* nothing to do */ return; /* nothing to do */
} }
for(j=0;j<y2;j++) for(j=0;j<y2;j++)
@ -452,9 +428,7 @@ void rfbDrawCursor(rfbClientPtr cl)
rfbMarkRectAsModified(s,x1,y1,x1+x2,y1+y2); rfbMarkRectAsModified(s,x1,y1,x1+x2,y1+y2);
s->cursorIsDrawn = TRUE; s->cursorIsDrawn = TRUE;
#ifdef HAVE_PTHREADS UNLOCK(cl->screen->cursorMutex);
pthread_mutex_unlock(&c->mutex);
#endif
} }
/* for debugging */ /* for debugging */
@ -475,26 +449,21 @@ void rfbPrintXCursor(rfbCursorPtr cursor)
extern void rfbSetCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr c,Bool freeOld) extern void rfbSetCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr c,Bool freeOld)
{ {
rfbClientIteratorPtr i = rfbGetClientIterator(rfbScreen);
rfbClientPtr cl; rfbClientPtr cl;
#ifdef HAVE_PTHREADS
pthread_mutex_lock(rfbScreen->cursor->mutex); LOCK(rfbScreen->cursorMutex);
#endif
for(cl=rfbScreen->rfbClientHead;cl;cl=cl->next) while((cl=rfbClientIteratorNext(i))) {
if(cl->sock>=0) { LOCK(cl->updateMutex);
#ifdef HAVE_PTHREADS rfbUndrawCursor(cl);
pthread_mutex_lock(cl->updateMutex); UNLOCK(cl->updateMutex);
#endif
rfbUndrawCursor(cl);
#ifdef HAVE_PTHREADS
pthread_mutex_unlock(cl->updateMutex);
#endif
} }
#ifdef HAVE_PTHREADS
pthread_mutex_unlock(rfbScreen->cursor->mutex);
#endif
if(freeOld && rfbScreen->cursor) if(freeOld && rfbScreen->cursor)
rfbFreeCursor(rfbScreen->cursor); rfbFreeCursor(rfbScreen->cursor);
rfbScreen->cursor = c; rfbScreen->cursor = c;
UNLOCK(rfbScreen->cursorMutex);
} }

@ -34,12 +34,14 @@ static void desfunc(unsigned long *, unsigned long *);
static void cookey(unsigned long *); static void cookey(unsigned long *);
static unsigned long KnL[32] = { 0L }; static unsigned long KnL[32] = { 0L };
/*
static unsigned long KnR[32] = { 0L }; static unsigned long KnR[32] = { 0L };
static unsigned long Kn3[32] = { 0L }; static unsigned long Kn3[32] = { 0L };
static unsigned char Df_Key[24] = { static unsigned char Df_Key[24] = {
0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,
0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10, 0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10,
0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 }; 0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 };
*/
static unsigned short bytebit[8] = { static unsigned short bytebit[8] = {
01, 02, 04, 010, 020, 040, 0100, 0200 }; 01, 02, 04, 010, 020, 040, 0100, 0200 };

@ -75,14 +75,10 @@ void rfbMarkRegionAsModified(rfbScreenInfoPtr rfbScreen,sraRegionPtr modRegion)
iterator=rfbGetClientIterator(rfbScreen); iterator=rfbGetClientIterator(rfbScreen);
while((cl=rfbClientIteratorNext(iterator))) { while((cl=rfbClientIteratorNext(iterator))) {
#ifdef HAVE_PTHREADS LOCK(cl->updateMutex);
pthread_mutex_lock(&cl->updateMutex);
#endif
sraRgnOr(cl->modifiedRegion,modRegion); sraRgnOr(cl->modifiedRegion,modRegion);
#ifdef HAVE_PTHREADS SIGNAL(cl->updateCond);
pthread_cond_signal(&cl->updateCond); UNLOCK(cl->updateMutex);
pthread_mutex_unlock(&cl->updateMutex);
#endif
} }
rfbReleaseClientIterator(iterator); rfbReleaseClientIterator(iterator);
@ -120,11 +116,11 @@ clientOutput(void *data)
while (1) { while (1) {
haveUpdate = false; haveUpdate = false;
pthread_mutex_lock(&cl->updateMutex); LOCK(cl->updateMutex);
while (!haveUpdate) { while (!haveUpdate) {
if (cl->sock == -1) { if (cl->sock == -1) {
/* Client has disconnected. */ /* Client has disconnected. */
pthread_mutex_unlock(&cl->updateMutex); UNLOCK(cl->updateMutex);
return NULL; return NULL;
} }
updateRegion = sraRgnCreateRgn(cl->modifiedRegion); updateRegion = sraRgnCreateRgn(cl->modifiedRegion);
@ -132,24 +128,24 @@ clientOutput(void *data)
sraRgnDestroy(updateRegion); sraRgnDestroy(updateRegion);
if (!haveUpdate) { 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 /* OK, now, to save bandwidth, wait a little while for more
updates to come along. */ updates to come along. */
pthread_mutex_unlock(&cl->updateMutex); UNLOCK(cl->updateMutex);
usleep(rfbDeferUpdateTime * 1000); usleep(rfbDeferUpdateTime * 1000);
/* Now, get the region we're going to update, and remove /* Now, get the region we're going to update, and remove
it from cl->modifiedRegion _before_ we send the update. it from cl->modifiedRegion _before_ we send the update.
That way, if anything that overlaps the region we're sending That way, if anything that overlaps the region we're sending
is updated, we'll be sure to do another update later. */ is updated, we'll be sure to do another update later. */
pthread_mutex_lock(&cl->updateMutex); LOCK(cl->updateMutex);
updateRegion = sraRgnCreateRgn(cl->modifiedRegion); updateRegion = sraRgnCreateRgn(cl->modifiedRegion);
sraRgnAnd(updateRegion,cl->requestedRegion); sraRgnAnd(updateRegion,cl->requestedRegion);
sraRgnSubtract(cl->modifiedRegion,updateRegion); sraRgnSubtract(cl->modifiedRegion,updateRegion);
pthread_mutex_unlock(&cl->updateMutex); UNLOCK(cl->updateMutex);
/* Now actually send the update. */ /* Now actually send the update. */
rfbSendFramebufferUpdate(cl, updateRegion); rfbSendFramebufferUpdate(cl, updateRegion);
@ -176,10 +172,10 @@ clientInput(void *data)
} }
/* Get rid of the output thread. */ /* Get rid of the output thread. */
pthread_mutex_lock(&cl->updateMutex); LOCK(cl->updateMutex);
pthread_cond_signal(&cl->updateCond); SIGNAL(cl->updateCond);
pthread_mutex_unlock(&cl->updateMutex); UNLOCK(cl->updateMutex);
pthread_join(output_thread, NULL); IF_PTHREADS(pthread_join(output_thread, NULL));
rfbClientConnectionGone(cl); rfbClientConnectionGone(cl);
@ -389,6 +385,7 @@ rfbScreenInfoPtr rfbGetScreen(int argc,char** argv,
rfbScreen->dontSendFramebufferUpdate = FALSE; rfbScreen->dontSendFramebufferUpdate = FALSE;
rfbScreen->cursorX=rfbScreen->cursorY=rfbScreen->underCursorBufferLen=0; rfbScreen->cursorX=rfbScreen->cursorY=rfbScreen->underCursorBufferLen=0;
rfbScreen->underCursorBuffer=NULL; rfbScreen->underCursorBuffer=NULL;
//INIT_MUTEX(rfbScreen->cursorMutex);
/* proc's and hook's */ /* proc's and hook's */
@ -410,6 +407,11 @@ rfbScreenInfoPtr rfbGetScreen(int argc,char** argv,
void rfbScreenCleanup(rfbScreenInfoPtr rfbScreen) void rfbScreenCleanup(rfbScreenInfoPtr rfbScreen)
{ {
/* TODO */ /* TODO */
if(rfbScreen->frameBuffer)
free(rfbScreen->frameBuffer);
if(rfbScreen->colourMap.data.bytes)
free(rfbScreen->colourMap.data.bytes);
TINI_MUTEX(rfbScreen->cursorMutex);
free(rfbScreen); free(rfbScreen);
} }
@ -422,7 +424,8 @@ void rfbInitServer(rfbScreenInfoPtr rfbScreen)
void void
rfbProcessEvents(rfbScreenInfoPtr rfbScreen,long usec) rfbProcessEvents(rfbScreenInfoPtr rfbScreen,long usec)
{ {
rfbClientPtr cl,cl_next; rfbClientIteratorPtr i;
rfbClientPtr cl;
rfbCheckFds(rfbScreen,usec); rfbCheckFds(rfbScreen,usec);
httpCheckFds(rfbScreen); httpCheckFds(rfbScreen);
@ -430,17 +433,14 @@ rfbProcessEvents(rfbScreenInfoPtr rfbScreen,long usec)
corbaCheckFds(rfbScreen); corbaCheckFds(rfbScreen);
#endif #endif
/* this needn't be thread safe: i = rfbGetClientIterator(rfbScreen);
you use rfbRunEventLoop(..,TRUE) for pthreads. */ while((cl=rfbClientIteratorNext(i))) {
cl=rfbScreen->rfbClientHead;
while(cl) {
cl_next=cl->next;
if(cl->sock>=0 && FB_UPDATE_PENDING(cl)) if(cl->sock>=0 && FB_UPDATE_PENDING(cl))
rfbSendFramebufferUpdate(cl,cl->modifiedRegion); rfbSendFramebufferUpdate(cl,cl->modifiedRegion);
if(cl->sock==-1) if(cl->sock==-1)
rfbClientConnectionGone(cl); rfbClientConnectionGone(cl);
cl=cl_next;
} }
rfbReleaseClientIterator(i);
} }
void rfbRunEventLoop(rfbScreenInfoPtr rfbScreen, long usec, Bool runInBackground) void rfbRunEventLoop(rfbScreenInfoPtr rfbScreen, long usec, Bool runInBackground)

71
rfb.h

@ -52,15 +52,6 @@ int max(int,int);
#include <rfbproto.h> #include <rfbproto.h>
#ifdef HAVE_PTHREADS
#include <pthread.h>
#define IF_PTHREADS(x) (x)
#else
#define IF_PTHREADS(x)
#endif
#ifdef __linux__ #ifdef __linux__
#include <endian.h> #include <endian.h>
#else #else
@ -84,6 +75,47 @@ int max(int,int);
#include <netinet/in.h> #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 #define MAX_ENCODINGS 10
struct rfbClientRec; struct rfbClientRec;
@ -210,6 +242,7 @@ typedef struct
Bool rfbDontDisconnect; Bool rfbDontDisconnect;
struct rfbClientRec* rfbClientHead; struct rfbClientRec* rfbClientHead;
struct rfbCursor* cursor; struct rfbCursor* cursor;
MUTEX(cursorMutex);
/* the following members have to be supplied by the serving process */ /* the following members have to be supplied by the serving process */
char* frameBuffer; char* frameBuffer;
@ -273,7 +306,7 @@ typedef struct rfbClientRec {
*/ */
void* clientData; void* clientData;
ClientGoneHookPtr clientGoneHook; ClientGoneHookPtr clientGoneHook;
int sock; int sock;
char *host; char *host;
/* Possible client states: */ /* Possible client states: */
@ -324,10 +357,17 @@ typedef struct rfbClientRec {
#ifdef HAVE_PTHREADS #ifdef HAVE_PTHREADS
pthread_mutex_t dontKillMutex; /* if you need a reliable clientPtr */ /* whenever a client is referenced, the refCount has to be incremented
pthread_mutex_t outputMutex; and afterwards decremented.
pthread_mutex_t updateMutex; Use the functions rfbIncrClientRef(cl) and rfbDecrClientRef(cl);
pthread_cond_t updateCond; */
int refCount;
MUTEX(refCountMutex);
COND(deleteCond);
MUTEX(outputMutex);
MUTEX(updateMutex);
COND(updateCond);
#endif #endif
sraRegionPtr modifiedRegion; sraRegionPtr modifiedRegion;
@ -598,9 +638,6 @@ typedef struct rfbCursor {
unsigned short foreRed, foreGreen, foreBlue; /* device-independent colour */ unsigned short foreRed, foreGreen, foreBlue; /* device-independent colour */
unsigned short backRed, backGreen, backBlue; /* device-independent colour */ unsigned short backRed, backGreen, backBlue; /* device-independent colour */
unsigned char *richSource; /* source bytes for a rich cursor */ unsigned char *richSource; /* source bytes for a rich cursor */
#ifdef HAVE_PTHREADS
pthread_mutex_t mutex;
#endif
} rfbCursor, *rfbCursorPtr; } rfbCursor, *rfbCursorPtr;
extern Bool rfbSendCursorShape(rfbClientPtr cl/*, rfbScreenInfoPtr pScreen*/); extern Bool rfbSendCursorShape(rfbClientPtr cl/*, rfbScreenInfoPtr pScreen*/);

@ -33,9 +33,6 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#ifdef HAVE_PTHREADS
#include <pthread.h>
#endif
rfbClientPtr pointerClient = NULL; /* Mutex for pointer events */ rfbClientPtr pointerClient = NULL; /* Mutex for pointer events */
@ -43,52 +40,74 @@ static void rfbProcessClientProtocolVersion(rfbClientPtr cl);
static void rfbProcessClientNormalMessage(rfbClientPtr cl); static void rfbProcessClientNormalMessage(rfbClientPtr cl);
static void rfbProcessClientInitMessage(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 { struct rfbClientIterator {
rfbClientPtr next; rfbClientPtr next;
rfbScreenInfoPtr screen;
}; };
#ifdef HAVE_PTHREADS
static pthread_mutex_t rfbClientListMutex;
#endif
static struct rfbClientIterator rfbClientIteratorInstance;
void void
rfbClientListInit(rfbScreenInfoPtr rfbScreen) rfbClientListInit(rfbScreenInfoPtr rfbScreen)
{ {
rfbScreen->rfbClientHead = NULL; rfbScreen->rfbClientHead = NULL;
#ifdef HAVE_PTHREADS
pthread_mutex_init(&rfbClientListMutex, NULL);
#endif
} }
rfbClientIteratorPtr rfbClientIteratorPtr
rfbGetClientIterator(rfbScreenInfoPtr rfbScreen) rfbGetClientIterator(rfbScreenInfoPtr rfbScreen)
{ {
#ifdef HAVE_PTHREADS rfbClientIteratorPtr i =
pthread_mutex_lock(&rfbClientListMutex); (rfbClientIteratorPtr)malloc(sizeof(struct rfbClientIterator));
#endif i->next = 0;
rfbClientIteratorInstance.next = rfbScreen->rfbClientHead; i->screen = rfbScreen;
return i;
return &rfbClientIteratorInstance;
} }
rfbClientPtr rfbClientPtr
rfbClientIteratorNext(rfbClientIteratorPtr iterator) rfbClientIteratorNext(rfbClientIteratorPtr i)
{ {
rfbClientPtr result; if(i->next == 0) {
result = iterator->next; LOCK(rfbClientListMutex);
if (result) i->next = i->screen->rfbClientHead;
iterator->next = result->next; UNLOCK(rfbClientListMutex);
return result; } 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 void
rfbReleaseClientIterator(rfbClientIteratorPtr iterator) rfbReleaseClientIterator(rfbClientIteratorPtr iterator)
{ {
#ifdef HAVE_PTHREADS IF_PTHREADS(if(iterator->next) rfbDecrClientRef(iterator->next));
pthread_mutex_unlock(&rfbClientListMutex);
#endif
} }
@ -169,9 +188,7 @@ rfbNewClient(rfbScreen,sock)
getpeername(sock, (struct sockaddr *)&addr, &addrlen); getpeername(sock, (struct sockaddr *)&addr, &addrlen);
cl->host = strdup(inet_ntoa(addr.sin_addr)); cl->host = strdup(inet_ntoa(addr.sin_addr));
#ifdef HAVE_PTHREADS INIT_MUTEX(cl->outputMutex);
pthread_mutex_init(&cl->outputMutex, NULL);
#endif
cl->state = RFB_PROTOCOL_VERSION; cl->state = RFB_PROTOCOL_VERSION;
@ -189,10 +206,8 @@ rfbNewClient(rfbScreen,sock)
cl->modifiedRegion = cl->modifiedRegion =
sraRgnCreateRect(0,0,rfbScreen->width,rfbScreen->height); sraRgnCreateRect(0,0,rfbScreen->width,rfbScreen->height);
#ifdef HAVE_PTHREADS INIT_MUTEX(cl->updateMutex);
pthread_mutex_init(&cl->updateMutex, NULL); INIT_COND(cl->updateCond);
pthread_cond_init(&cl->updateCond, NULL);
#endif
cl->requestedRegion = sraRgnCreate(); cl->requestedRegion = sraRgnCreate();
@ -200,18 +215,16 @@ rfbNewClient(rfbScreen,sock)
cl->translateFn = rfbTranslateNone; cl->translateFn = rfbTranslateNone;
cl->translateLookupTable = NULL; cl->translateLookupTable = NULL;
#ifdef HAVE_PTHREADS LOCK(rfbClientListMutex);
pthread_mutex_lock(&rfbClientListMutex);
#endif cl->refCount = 0;
cl->next = rfbScreen->rfbClientHead; cl->next = rfbScreen->rfbClientHead;
cl->prev = NULL; cl->prev = NULL;
if (rfbScreen->rfbClientHead) if (rfbScreen->rfbClientHead)
rfbScreen->rfbClientHead->prev = cl; rfbScreen->rfbClientHead->prev = cl;
rfbScreen->rfbClientHead = cl; rfbScreen->rfbClientHead = cl;
#ifdef HAVE_PTHREADS UNLOCK(rfbClientListMutex);
pthread_mutex_unlock(&rfbClientListMutex);
#endif
cl->tightCompressLevel = TIGHT_DEFAULT_COMPRESSION; cl->tightCompressLevel = TIGHT_DEFAULT_COMPRESSION;
cl->tightQualityLevel = -1; cl->tightQualityLevel = -1;
@ -261,12 +274,23 @@ rfbClientConnectionGone(cl)
{ {
int i; 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 #ifdef HAVE_PTHREADS
/* LOCK(cl->refCountMutex);
pthread_mutex_lock(&cl->updateMutex); if(cl->refCount) {
pthread_mutex_lock(&cl->outputMutex); UNLOCK(cl->refCountMutex);
*/ WAIT(cl->deleteCond,cl->refCountMutex);
pthread_mutex_lock(&rfbClientListMutex); } else {
UNLOCK(cl->refCountMutex);
}
#endif #endif
cl->clientGoneHook(cl); cl->clientGoneHook(cl);
@ -287,28 +311,19 @@ rfbClientConnectionGone(cl)
if (pointerClient == cl) if (pointerClient == cl)
pointerClient = NULL; 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); sraRgnDestroy(cl->modifiedRegion);
rfbPrintStats(cl); UNLOCK(rfbClientListMutex);
if (cl->translateLookupTable) free(cl->translateLookupTable); if (cl->translateLookupTable) free(cl->translateLookupTable);
#ifdef HAVE_PTHREADS TINI_COND(cl->updateCond);
pthread_mutex_unlock(&rfbClientListMutex); TINI_MUTEX(cl->updateMutex);
#endif
#ifdef HAVE_PTHREADS LOCK(cl->outputMutex);
pthread_cond_destroy(&cl->updateCond); TINI_MUTEX(cl->outputMutex);
pthread_mutex_destroy(&cl->updateMutex);
pthread_mutex_destroy(&cl->outputMutex); rfbPrintStats(cl);
#endif
xfree(cl); xfree(cl);
} }
@ -694,9 +709,7 @@ rfbProcessClientNormalMessage(cl)
Swap16IfLE(msg.fur.x)+Swap16IfLE(msg.fur.w), Swap16IfLE(msg.fur.x)+Swap16IfLE(msg.fur.w),
Swap16IfLE(msg.fur.y)+Swap16IfLE(msg.fur.h)); Swap16IfLE(msg.fur.y)+Swap16IfLE(msg.fur.h));
#ifdef HAVE_PTHREADS LOCK(cl->updateMutex);
pthread_mutex_lock(&cl->updateMutex);
#endif
sraRgnOr(cl->requestedRegion,tmpRegion); sraRgnOr(cl->requestedRegion,tmpRegion);
if (!cl->readyForSetColourMapEntries) { if (!cl->readyForSetColourMapEntries) {
@ -713,19 +726,16 @@ rfbProcessClientNormalMessage(cl)
if (!msg.fur.incremental) { if (!msg.fur.incremental) {
sraRgnOr(cl->modifiedRegion,tmpRegion); sraRgnOr(cl->modifiedRegion,tmpRegion);
sraRgnSubtract(cl->copyRegion,tmpRegion); sraRgnSubtract(cl->copyRegion,tmpRegion);
} }
#ifdef HAVE_PTHREADS SIGNAL(cl->updateCond);
pthread_cond_signal(&cl->updateCond); UNLOCK(cl->updateMutex);
pthread_mutex_unlock(&cl->updateMutex);
#endif
if(cl->sock>=0 && FB_UPDATE_PENDING(cl)) {
rfbSendFramebufferUpdate(cl,cl->modifiedRegion);
}
sraRgnDestroy(tmpRegion); if(cl->sock>=0 && FB_UPDATE_PENDING(cl)) {
rfbSendFramebufferUpdate(cl,cl->modifiedRegion);
}
sraRgnDestroy(tmpRegion);
return; return;
} }
case rfbKeyEvent: case rfbKeyEvent:
@ -1209,6 +1219,9 @@ Bool
rfbSendUpdateBuf(cl) rfbSendUpdateBuf(cl)
rfbClientPtr cl; rfbClientPtr cl;
{ {
if(cl->sock<0)
return FALSE;
if (WriteExact(cl, cl->updateBuf, cl->ublen) < 0) { if (WriteExact(cl, cl->updateBuf, cl->ublen) < 0) {
rfbLogPerror("rfbSendUpdateBuf: write"); rfbLogPerror("rfbSendUpdateBuf: write");
rfbCloseClient(cl); rfbCloseClient(cl);
@ -1275,17 +1288,19 @@ rfbSendSetColourMapEntries(cl, firstColour, nColours)
void void
rfbSendBell(rfbScreenInfoPtr rfbScreen) rfbSendBell(rfbScreenInfoPtr rfbScreen)
{ {
rfbClientPtr cl, nextCl; rfbClientIteratorPtr i;
rfbClientPtr cl;
rfbBellMsg b; rfbBellMsg b;
for (cl = rfbScreen->rfbClientHead; cl; cl = nextCl) { i = rfbGetClientIterator(rfbScreen);
nextCl = cl->next; while((cl=rfbClientIteratorNext(i))) {
b.type = rfbBell; b.type = rfbBell;
if (WriteExact(cl, (char *)&b, sz_rfbBellMsg) < 0) { if (WriteExact(cl, (char *)&b, sz_rfbBellMsg) < 0) {
rfbLogPerror("rfbSendBell: write"); rfbLogPerror("rfbSendBell: write");
rfbCloseClient(cl); rfbCloseClient(cl);
} }
} }
rfbReleaseClientIterator(i);
} }

@ -142,7 +142,7 @@ rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec)
const int one = 1; const int one = 1;
int sock; int sock;
rfbClientIteratorPtr i; rfbClientIteratorPtr i;
rfbClientPtr cl,cl_next; rfbClientPtr cl;
if (!rfbScreen->inetdInitDone && rfbScreen->inetdSock != -1) { if (!rfbScreen->inetdInitDone && rfbScreen->inetdSock != -1) {
rfbNewClientConnection(rfbScreen,rfbScreen->inetdSock); rfbNewClientConnection(rfbScreen,rfbScreen->inetdSock);
@ -233,34 +233,12 @@ rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec)
return; 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); i = rfbGetClientIterator(rfbScreen);
cl = rfbClientIteratorNext(i); while((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
if (FD_ISSET(cl->sock, &fds) && FD_ISSET(cl->sock, &(rfbScreen->allFds))) if (FD_ISSET(cl->sock, &fds) && FD_ISSET(cl->sock, &(rfbScreen->allFds)))
rfbProcessClientMessage(cl); rfbProcessClientMessage(cl);
cl=cl_next;
} }
rfbReleaseClientIterator(i);
} }
@ -276,17 +254,12 @@ void
rfbCloseClient(cl) rfbCloseClient(cl)
rfbClientPtr cl; rfbClientPtr cl;
{ {
#ifdef HAVE_PTHREADS LOCK(cl->updateMutex);
pthread_mutex_lock(&cl->updateMutex);
#endif
FD_CLR(cl->sock,&(cl->screen->allFds)); FD_CLR(cl->sock,&(cl->screen->allFds));
close(cl->sock); close(cl->sock);
cl->sock = -1; cl->sock = -1;
#ifdef HAVE_PTHREADS SIGNAL(cl->updateCond);
pthread_cond_signal(&cl->updateCond); UNLOCK(cl->updateMutex);
//pthread_mutex_lock(&cl->updateMutex);
pthread_mutex_unlock(&cl->updateMutex);
#endif
} }
@ -362,9 +335,7 @@ WriteExact(cl, buf, len)
struct timeval tv; struct timeval tv;
int totalTimeWaited = 0; int totalTimeWaited = 0;
#ifdef HAVE_PTHREADS LOCK(cl->outputMutex);
pthread_mutex_lock(&cl->outputMutex);
#endif
while (len > 0) { while (len > 0) {
n = write(sock, buf, len); n = write(sock, buf, len);
@ -380,9 +351,7 @@ WriteExact(cl, buf, len)
} else { } else {
if (errno != EWOULDBLOCK && errno != EAGAIN) { if (errno != EWOULDBLOCK && errno != EAGAIN) {
#ifdef HAVE_PTHREADS UNLOCK(cl->outputMutex);
pthread_mutex_unlock(&cl->outputMutex);
#endif
return n; return n;
} }
@ -397,18 +366,14 @@ WriteExact(cl, buf, len)
n = select(sock+1, NULL, &fds, NULL, &tv); n = select(sock+1, NULL, &fds, NULL, &tv);
if (n < 0) { if (n < 0) {
rfbLogPerror("WriteExact: select"); rfbLogPerror("WriteExact: select");
#ifdef HAVE_PTHREADS UNLOCK(cl->outputMutex);
pthread_mutex_unlock(&cl->outputMutex);
#endif
return n; return n;
} }
if (n == 0) { if (n == 0) {
totalTimeWaited += 5000; totalTimeWaited += 5000;
if (totalTimeWaited >= rfbMaxClientWait) { if (totalTimeWaited >= rfbMaxClientWait) {
errno = ETIMEDOUT; errno = ETIMEDOUT;
#ifdef HAVE_PTHREADS UNLOCK(cl->outputMutex);
pthread_mutex_unlock(&cl->outputMutex);
#endif
return -1; return -1;
} }
} else { } else {
@ -416,9 +381,7 @@ WriteExact(cl, buf, len)
} }
} }
} }
#ifdef HAVE_PTHREADS UNLOCK(cl->outputMutex);
pthread_mutex_unlock(&cl->outputMutex);
#endif
return 1; return 1;
} }

@ -449,12 +449,13 @@ rfbSetClientColourMaps(rfbScreen, firstColour, nColours)
int firstColour; int firstColour;
int nColours; int nColours;
{ {
rfbClientPtr cl, nextCl; rfbClientIteratorPtr i;
rfbClientPtr cl;
for (cl = rfbScreen->rfbClientHead; cl; cl = nextCl) { i = rfbGetClientIterator(rfbScreen);
nextCl = cl->next; while((cl = rfbClientIteratorNext(i)))
rfbSetClientColourMap(cl, firstColour, nColours); rfbSetClientColourMap(cl, firstColour, nColours);
} rfbReleaseClientIterator(i);
} }
static void static void

@ -26,6 +26,7 @@
#include <string.h> #include <string.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/time.h>
#include "rfb.h" #include "rfb.h"
#include "d3des.h" #include "d3des.h"

Loading…
Cancel
Save