summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordscho <dscho>2002-02-18 06:43:54 +0000
committerdscho <dscho>2002-02-18 06:43:54 +0000
commit45a4b4a2235adecc925182b27959db62b5954a26 (patch)
treede00aee4fd77b81f768d00416c9eda47d21e22b3
parentfbf2c977fe4c70fa2e551ecc0264c4b8184386f2 (diff)
downloadlibtdevnc-45a4b4a2235adecc925182b27959db62b5954a26.tar.gz
libtdevnc-45a4b4a2235adecc925182b27959db62b5954a26.zip
changes from Tim Jansen: threading issues, new client can be rejected, and more
-rw-r--r--README2
-rw-r--r--cursor.c4
-rw-r--r--example.c3
-rw-r--r--httpd.c6
-rw-r--r--main.c57
-rw-r--r--rfb.h74
-rw-r--r--rfbserver.c25
-rw-r--r--sockets.c44
-rw-r--r--tight.c3
-rw-r--r--translate.c5
10 files changed, 160 insertions, 63 deletions
diff --git a/README b/README
index 78df927..fe6d0c0 100644
--- a/README
+++ b/README
@@ -83,7 +83,7 @@ Whenever you draw something, you have to call
This tells LibVNCServer to send updates to all connected clients.
Before you draw something, be sure to call
- rfbUndrawCursor(cl).
+ rfbUndrawCursor(screen).
This tells LibVNCServer to hide the cursor.
Remark: There are vncviewers out there, which know a cursor encoding, so
that network traffic is low, and also the cursor doesn't need to be
diff --git a/cursor.c b/cursor.c
index 5e86de1..057ff5e 100644
--- a/cursor.c
+++ b/cursor.c
@@ -42,7 +42,7 @@ rfbSendCursorShape(cl)
CARD8 bitmapByte;
pCursor = cl->screen->getCursorPtr(cl);
- //if(!pCursor) return TRUE;
+ /*if(!pCursor) return TRUE;*/
if (cl->useRichCursorEncoding) {
if(pCursor && !pCursor->richSource)
@@ -227,7 +227,7 @@ rfbCursorPtr rfbMakeXCursor(int width,int height,char* cursorString,char* maskSt
cursor->width=width;
cursor->height=height;
- //cursor->backRed=cursor->backGreen=cursor->backBlue=0xffff;
+ /*cursor->backRed=cursor->backGreen=cursor->backBlue=0xffff;*/
cursor->foreRed=cursor->foreGreen=cursor->foreBlue=0xffff;
cursor->source = (char*)calloc(w,height);
diff --git a/example.c b/example.c
index a3cfba9..41165c7 100644
--- a/example.c
+++ b/example.c
@@ -67,10 +67,11 @@ void clientgone(rfbClientPtr cl)
free(cl->clientData);
}
-void newclient(rfbClientPtr cl)
+enum rfbNewClientAction newclient(rfbClientPtr cl)
{
cl->clientData = (void*)calloc(sizeof(ClientData),1);
cl->clientGoneHook = clientgone;
+ return RFB_CLIENT_ACCEPT;
}
/* aux function to draw a line */
diff --git a/httpd.c b/httpd.c
index fd00ec2..37be4f3 100644
--- a/httpd.c
+++ b/httpd.c
@@ -92,7 +92,7 @@ httpInitSockets(rfbScreenInfoPtr rfbScreen)
exit(1);
}
- //AddEnabledDevice(httpListenSock);
+ /*AddEnabledDevice(httpListenSock);*/
}
@@ -151,7 +151,7 @@ httpCheckFds(rfbScreenInfoPtr rfbScreen)
return;
}
- //AddEnabledDevice(httpSock);
+ /*AddEnabledDevice(httpSock);*/
}
}
@@ -161,7 +161,7 @@ httpCloseSock(rfbScreenInfoPtr rfbScreen)
{
fclose(rfbScreen->httpFP);
rfbScreen->httpFP = NULL;
- //RemoveEnabledDevice(httpSock);
+ /*RemoveEnabledDevice(httpSock);*/
rfbScreen->httpSock = -1;
}
diff --git a/main.c b/main.c
index 5e39ae5..3f4580d 100644
--- a/main.c
+++ b/main.c
@@ -41,7 +41,7 @@ char rfbEndianTest = (_BYTE_ORDER == _LITTLE_ENDIAN);
*/
void
-rfbLog(char *format, ...)
+rfbLog(const char *format, ...)
{
va_list args;
char buf[256];
@@ -61,7 +61,7 @@ rfbLog(char *format, ...)
UNLOCK(logMutex);
}
-void rfbLogPerror(char *str)
+void rfbLogPerror(const char *str)
{
rfbLog("%s: %s\n", str, strerror(errno));
}
@@ -128,7 +128,7 @@ void rfbScheduleCopyRegion(rfbScreenInfoPtr rfbScreen,sraRegionPtr copyRegion,in
} else {
sraRgnOr(cl->modifiedRegion,copyRegion);
}
- SIGNAL(cl->updateCond);
+ TSIGNAL(cl->updateCond);
UNLOCK(cl->updateMutex);
}
@@ -186,7 +186,7 @@ void rfbMarkRegionAsModified(rfbScreenInfoPtr rfbScreen,sraRegionPtr modRegion)
while((cl=rfbClientIteratorNext(iterator))) {
LOCK(cl->updateMutex);
sraRgnOr(cl->modifiedRegion,modRegion);
- SIGNAL(cl->updateCond);
+ TSIGNAL(cl->updateCond);
UNLOCK(cl->updateMutex);
}
@@ -281,7 +281,7 @@ clientInput(void *data)
/* Get rid of the output thread. */
LOCK(cl->updateMutex);
- SIGNAL(cl->updateCond);
+ TSIGNAL(cl->updateCond);
UNLOCK(cl->updateMutex);
IF_PTHREADS(pthread_join(output_thread, NULL));
@@ -290,31 +290,52 @@ clientInput(void *data)
return NULL;
}
-void*
+static void*
listenerRun(void *data)
{
rfbScreenInfoPtr rfbScreen=(rfbScreenInfoPtr)data;
int client_fd;
struct sockaddr_in peer;
- pthread_t client_thread;
rfbClientPtr cl;
int len;
len = sizeof(peer);
+
+ /* TODO: this thread wont die by restarting the server */
while ((client_fd = accept(rfbScreen->rfbListenSock,
- (struct sockaddr *)&peer, &len)) >= 0) {
+ (struct sockaddr*)&peer, &len)) >= 0) {
cl = rfbNewClient(rfbScreen,client_fd);
-
- pthread_create(&client_thread, NULL, clientInput, (void *)cl);
len = sizeof(peer);
+
+ if (cl && !cl->onHold )
+ rfbStartOnHoldClient(cl);
}
+}
+
+void
+rfbStartOnHoldClient(rfbClientPtr cl)
+{
+ pthread_create(&cl->client_thread, NULL, clientInput, (void *)cl);
+}
- rfbLog("accept failed\n");
- exit(1);
+#else
+
+void
+rfbStartOnHoldClient(rfbClientPtr cl)
+{
+ cl->onHold = FALSE;
}
+
#endif
-void
+void
+rfbRefuseOnHoldClient(rfbClientPtr cl)
+{
+ rfbCloseClient(cl);
+ rfbClientConnectionGone(cl);
+}
+
+static void
defaultKbdAddEvent(Bool down, KeySym keySym, rfbClientPtr cl)
{
}
@@ -423,6 +444,11 @@ void doNothingWithClient(rfbClientPtr cl)
{
}
+enum rfbNewClientAction defaultNewClientHook(rfbClientPtr cl)
+{
+ return RFB_CLIENT_ACCEPT;
+}
+
rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,
int width,int height,int bitsPerSample,int samplesPerPixel,
int bytesPerPixel)
@@ -435,6 +461,7 @@ rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,
if(width&3)
fprintf(stderr,"WARNING: Width (%d) is not a multiple of 4. VncViewer has problems with that.\n",width);
+ rfbScreen->autoPort=FALSE;
rfbScreen->rfbClientHead=0;
rfbScreen->rfbPort=5900;
rfbScreen->socketInitDone=FALSE;
@@ -536,7 +563,7 @@ rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,
rfbScreen->setXCutText = defaultSetXCutText;
rfbScreen->getCursorPtr = defaultGetCursorPtr;
rfbScreen->setTranslateFunction = rfbSetTranslateFunction;
- rfbScreen->newClientHook = doNothingWithClient;
+ rfbScreen->newClientHook = defaultNewClientHook;
rfbScreen->displayHook = 0;
/* initialize client list and iterator mutex */
@@ -597,7 +624,7 @@ rfbProcessEvents(rfbScreenInfoPtr rfbScreen,long usec)
i = rfbGetClientIterator(rfbScreen);
cl=rfbClientIteratorNext(i);
while(cl) {
- if(cl->sock>=0 && FB_UPDATE_PENDING(cl)) {
+ if(cl->sock>=0 && (!cl->onHold) && FB_UPDATE_PENDING(cl)) {
if(cl->screen->rfbDeferUpdateTime == 0) {
rfbSendFramebufferUpdate(cl,cl->modifiedRegion);
} else if(cl->startDeferring.tv_usec == 0) {
diff --git a/rfb.h b/rfb.h
index 35dd031..e39c2a6 100644
--- a/rfb.h
+++ b/rfb.h
@@ -26,6 +26,11 @@
* USA.
*/
+#if(defined __cplusplus)
+extern "C"
+{
+#endif
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -90,7 +95,7 @@ typedef unsigned long KeySym;
#undef SOCKET
#define SOCKET int
#else
-int max(int,int);
+#define max(a,b) (((a)>(b))?(a):(b))
#include <sys/time.h>
#include <netinet/in.h>
#define SOCKET int
@@ -116,7 +121,7 @@ int max(int,int);
#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 TSIGNAL(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)
@@ -129,7 +134,7 @@ int max(int,int);
#define MUTEX(mutex)
#define INIT_MUTEX(mutex)
#define TINI_MUTEX(mutex)
-#define SIGNAL(cond)
+#define TSIGNAL(cond)
#define WAIT(cond,mutex) this_is_unsupported
#define COND(cond)
#define INIT_COND(cond)
@@ -151,19 +156,25 @@ int max(int,int);
#define MAX_ENCODINGS 10
-struct rfbClientRec;
-struct rfbScreenInfo;
+struct _rfbClientRec;
+struct _rfbScreenInfo;
struct rfbCursor;
-typedef void (*KbdAddEventProcPtr) (Bool down, KeySym keySym, struct rfbClientRec* cl);
-typedef void (*KbdReleaseAllKeysProcPtr) (struct rfbClientRec* cl);
-typedef void (*PtrAddEventProcPtr) (int buttonMask, int x, int y, struct rfbClientRec* cl);
-typedef void (*SetXCutTextProcPtr) (char* str,int len, struct rfbClientRec* cl);
-typedef struct rfbCursor* (*GetCursorProcPtr) (struct rfbClientRec* pScreen);
-typedef Bool (*SetTranslateFunctionProcPtr)(struct rfbClientRec* cl);
-typedef Bool (*PasswordCheckProcPtr)(struct rfbClientRec* cl,char* encryptedPassWord,int len);
-typedef void (*NewClientHookPtr)(struct rfbClientRec* cl);
-typedef void (*DisplayHookPtr)(struct rfbClientRec* cl);
+enum rfbNewClientAction {
+ RFB_CLIENT_ACCEPT,
+ RFB_CLIENT_ON_HOLD,
+ RFB_CLIENT_REFUSE
+};
+
+typedef void (*KbdAddEventProcPtr) (Bool down, KeySym keySym, struct _rfbClientRec* cl);
+typedef void (*KbdReleaseAllKeysProcPtr) (struct _rfbClientRec* cl);
+typedef void (*PtrAddEventProcPtr) (int buttonMask, int x, int y, struct _rfbClientRec* cl);
+typedef void (*SetXCutTextProcPtr) (char* str,int len, struct _rfbClientRec* cl);
+typedef struct rfbCursor* (*GetCursorProcPtr) (struct _rfbClientRec* pScreen);
+typedef Bool (*SetTranslateFunctionProcPtr)(struct _rfbClientRec* cl);
+typedef Bool (*PasswordCheckProcPtr)(struct _rfbClientRec* cl,char* encryptedPassWord,int len);
+typedef enum rfbNewClientAction (*NewClientHookPtr)(struct _rfbClientRec* cl);
+typedef void (*DisplayHookPtr)(struct _rfbClientRec* cl);
typedef struct {
CARD32 count;
@@ -180,7 +191,7 @@ typedef struct {
* rfbProcessEvents for each of these.
*/
-typedef struct
+typedef struct _rfbScreenInfo
{
int width;
int paddedWidthInBytes;
@@ -246,6 +257,7 @@ typedef struct
char* desktopName;
char rfbThisHost[255];
+ Bool autoPort;
int rfbPort;
SOCKET rfbListenSock;
int maxSock;
@@ -258,7 +270,7 @@ typedef struct
int udpPort;
SOCKET udpSock;
- struct rfbClientRec* udpClient;
+ struct _rfbClientRec* udpClient;
Bool udpSockConnected;
struct sockaddr_in udpRemoteAddr;
@@ -282,7 +294,7 @@ typedef struct
Bool rfbAlwaysShared;
Bool rfbNeverShared;
Bool rfbDontDisconnect;
- struct rfbClientRec* rfbClientHead;
+ struct _rfbClientRec* rfbClientHead;
/* cursor */
int cursorX, cursorY,underCursorBufferLen;
@@ -346,9 +358,9 @@ typedef struct sraRegion* sraRegionPtr;
* Per-client structure.
*/
-typedef void (*ClientGoneHookPtr)(struct rfbClientRec* cl);
+typedef void (*ClientGoneHookPtr)(struct _rfbClientRec* cl);
-typedef struct rfbClientRec {
+typedef struct _rfbClientRec {
/* back pointer to the screen */
rfbScreenInfoPtr screen;
@@ -364,6 +376,10 @@ typedef struct rfbClientRec {
SOCKET sock;
char *host;
+
+#ifdef HAVE_PTHREADS
+ pthread_t client_thread;
+#endif
/* Possible client states: */
enum {
RFB_PROTOCOL_VERSION, /* establishing protocol version */
@@ -373,6 +389,7 @@ typedef struct rfbClientRec {
} state;
Bool reverseConnection;
+ Bool onHold;
Bool readyForSetColourMapEntries;
Bool useCopyRect;
int preferredEncoding;
@@ -477,8 +494,8 @@ typedef struct rfbClientRec {
Bool enableBackChannel;
#endif
- struct rfbClientRec *prev;
- struct rfbClientRec *next;
+ struct _rfbClientRec *prev;
+ struct _rfbClientRec *next;
#ifdef HAVE_PTHREADS
/* whenever a client is referenced, the refCount has to be incremented
@@ -741,8 +758,8 @@ extern void rfbProcessSizeArguments(int* width,int* height,int* bpp,int* argc, c
/* main.c */
-extern void rfbLog(char *format, ...);
-extern void rfbLogPerror(char *str);
+extern void rfbLog(const char *format, ...);
+extern void rfbLogPerror(const char *str);
void rfbScheduleCopyRect(rfbScreenInfoPtr rfbScreen,int x1,int y1,int x2,int y2,int dx,int dy);
void rfbScheduleCopyRegion(rfbScreenInfoPtr rfbScreen,sraRegionPtr copyRegion,int dx,int dy);
@@ -753,6 +770,7 @@ void rfbDoCopyRegion(rfbScreenInfoPtr rfbScreen,sraRegionPtr copyRegion,int dx,i
void rfbMarkRectAsModified(rfbScreenInfoPtr rfbScreen,int x1,int y1,int x2,int y2);
void rfbMarkRegionAsModified(rfbScreenInfoPtr rfbScreen,sraRegionPtr modRegion);
void doNothingWithClient(rfbClientPtr cl);
+enum rfbNewClientAction defaultNewClientHook(rfbClientPtr cl);
/* to check against plain passwords */
Bool rfbCheckPasswordByList(rfbClientPtr cl,char* response,int len);
@@ -764,6 +782,12 @@ extern rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,
extern void rfbInitServer(rfbScreenInfoPtr rfbScreen);
extern void rfbScreenCleanup(rfbScreenInfoPtr screenInfo);
+/* functions to accept/refuse a client that has been put on hold
+ by a NewClientHookPtr function. Must not be called in other
+ situations. */
+extern void rfbStartOnHoldClient(rfbClientPtr cl);
+extern void rfbRefuseOnHoldClient(rfbClientPtr cl);
+
/* call one of these two functions to service the vnc clients.
usec are the microseconds the select on the fds waits.
if you are using the event loop, set this to some value > 0, so the
@@ -773,3 +797,7 @@ extern void rfbRunEventLoop(rfbScreenInfoPtr screenInfo, long usec, Bool runInBa
extern void rfbProcessEvents(rfbScreenInfoPtr screenInfo,long usec);
#endif
+
+#if(defined __cplusplus)
+}
+#endif
diff --git a/rfbserver.c b/rfbserver.c
index b938d91..2190aef 100644
--- a/rfbserver.c
+++ b/rfbserver.c
@@ -61,7 +61,7 @@ void rfbDecrClientRef(rfbClientPtr cl)
LOCK(cl->refCountMutex);
cl->refCount--;
if(cl->refCount<=0) /* just to be sure also < 0 */
- SIGNAL(cl->deleteCond);
+ TSIGNAL(cl->deleteCond);
UNLOCK(cl->refCountMutex);
}
#endif
@@ -271,14 +271,29 @@ rfbNewTCPOrUDPClient(rfbScreen,sock,isUDP)
if (WriteExact(cl, pv, sz_rfbProtocolVersionMsg) < 0) {
rfbLogPerror("rfbNewClient: write");
rfbCloseClient(cl);
+ /* TODO: memory leak here (cl is never freed)
+ * can rfbClientConnectionGone called at this time?
+ * tim@tjansen.de
+ */
return NULL;
}
}
cl->clientData = NULL;
cl->clientGoneHook = doNothingWithClient;
- cl->screen->newClientHook(cl);
-
+ switch (cl->screen->newClientHook(cl)) {
+ case RFB_CLIENT_ON_HOLD:
+ cl->onHold = TRUE;
+ break;
+ case RFB_CLIENT_ACCEPT:
+ cl->onHold = FALSE;
+ break;
+ case RFB_CLIENT_REFUSE:
+ rfbCloseClient(cl);
+ rfbClientConnectionGone(cl);
+ cl = NULL;
+ break;
+ }
return cl;
}
@@ -781,7 +796,7 @@ rfbProcessClientNormalMessage(cl)
sraRgnOr(cl->modifiedRegion,tmpRegion);
sraRgnSubtract(cl->copyRegion,tmpRegion);
}
- SIGNAL(cl->updateCond);
+ TSIGNAL(cl->updateCond);
UNLOCK(cl->updateMutex);
sraRgnDestroy(tmpRegion);
@@ -1431,7 +1446,7 @@ rfbProcessUDPInput(rfbScreenInfoPtr rfbScreen)
rfbClientPtr cl=rfbScreen->udpClient;
rfbClientToServerMsg msg;
- if(!cl)
+ if((!cl) || cl->onHold)
return;
if ((n = read(rfbScreen->udpSock, (char *)&msg, sizeof(msg))) <= 0) {
diff --git a/sockets.c b/sockets.c
index 4607420..1496f75 100644
--- a/sockets.c
+++ b/sockets.c
@@ -69,9 +69,10 @@ struct timeval
#include "rfb.h"
-//#ifndef WIN32
+/*#ifndef WIN32
int max(int i,int j) { return(i<j?j:i); }
-//#endif
+#endif
+*/
int rfbMaxClientWait = 20000; /* time (ms) after which we decide client has
gone away - needed to stop us hanging */
@@ -111,7 +112,28 @@ rfbInitSockets(rfbScreenInfoPtr rfbScreen)
return;
}
- if(rfbScreen->rfbPort>0) {
+ if(rfbScreen->autoPort) {
+ int i;
+ rfbLog("Autoprobing TCP port \n");
+
+ for (i = 5900; i < 6000; i++) {
+ if ((rfbScreen->rfbListenSock = ListenOnTCPPort(i)) >= 0) {
+ rfbScreen->rfbPort = i;
+ break;
+ }
+ }
+
+ if (i >= 6000) {
+ rfbLogPerror("Failure autoprobing");
+ exit(1);
+ }
+
+ rfbLog("Autoprobing selected port %d\n", rfbScreen->rfbPort);
+ FD_ZERO(&(rfbScreen->allFds));
+ FD_SET(rfbScreen->rfbListenSock, &(rfbScreen->allFds));
+ rfbScreen->maxFd = rfbScreen->rfbListenSock;
+ }
+ else if(rfbScreen->rfbPort>0) {
rfbLog("Listening for VNC connections on TCP port %d\n", rfbScreen->rfbPort);
if ((rfbScreen->rfbListenSock = ListenOnTCPPort(rfbScreen->rfbPort)) < 0) {
@@ -204,7 +226,7 @@ rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec)
rfbLog("Got connection from client %s\n", inet_ntoa(addr.sin_addr));
rfbNewClient(rfbScreen,sock);
-
+
FD_CLR(rfbScreen->rfbListenSock, &fds);
if (--nfds == 0)
return;
@@ -248,6 +270,8 @@ rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec)
i = rfbGetClientIterator(rfbScreen);
while((cl = rfbClientIteratorNext(i))) {
+ if (cl->onHold)
+ continue;
if (FD_ISSET(cl->sock, &fds) && FD_ISSET(cl->sock, &(rfbScreen->allFds)))
rfbProcessClientMessage(cl);
}
@@ -268,10 +292,12 @@ rfbCloseClient(cl)
rfbClientPtr cl;
{
LOCK(cl->updateMutex);
- FD_CLR(cl->sock,&(cl->screen->allFds));
- close(cl->sock);
- cl->sock = -1;
- SIGNAL(cl->updateCond);
+ if (cl->sock != -1) {
+ FD_CLR(cl->sock,&(cl->screen->allFds));
+ close(cl->sock);
+ cl->sock = -1;
+ }
+ TSIGNAL(cl->updateCond);
UNLOCK(cl->updateMutex);
}
@@ -360,7 +386,7 @@ ReadExact(cl, buf, len)
FD_SET(sock, &fds);
tv.tv_sec = rfbMaxClientWait / 1000;
tv.tv_usec = (rfbMaxClientWait % 1000) * 1000;
- n = select(sock+1, &fds, NULL, NULL, &tv);
+ n = select(sock+1, &fds, NULL, &fds, &tv);
if (n < 0) {
rfbLogPerror("ReadExact: select");
return n;
diff --git a/tight.c b/tight.c
index cae797d..f9f20f5 100644
--- a/tight.c
+++ b/tight.c
@@ -24,7 +24,7 @@
* USA.
*/
-//#include <stdio.h>
+/*#include <stdio.h>*/
#include "rfb.h"
#ifdef WIN32
@@ -35,7 +35,6 @@
#include <jpeglib.h>
-
/* Note: The following constant should not be changed. */
#define TIGHT_MIN_TO_COMPRESS 12
diff --git a/translate.c b/translate.c
index 8d78b99..f9e121d 100644
--- a/translate.c
+++ b/translate.c
@@ -259,8 +259,9 @@ rfbSetTranslateFunction(cl)
#endif
(cl->screen->rfbServerFormat.bitsPerPixel != 32))
{
- rfbLog("%s: server bits per pixel not 8, 16 or 32\n",
- "rfbSetTranslateFunction");
+ rfbLog("%s: server bits per pixel not 8, 16 or 32 (is %d)\n",
+ "rfbSetTranslateFunction",
+ cl->screen->rfbServerFormat.bitsPerPixel);
rfbCloseClient(cl);
return FALSE;
}