|
|
|
@ -2,6 +2,7 @@
|
|
|
|
|
* This file is called main.c, because it contains most of the new functions
|
|
|
|
|
* for use with LibVNCServer.
|
|
|
|
|
*
|
|
|
|
|
* Copyright (C) 2015 Timothy Pearson <kb9vqf@pearsoncomputing.net>.
|
|
|
|
|
* LibVNCServer (C) 2001 Johannes E. Schindelin <Johannes.Schindelin@gmx.de>
|
|
|
|
|
* Original OSXvnc (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
|
|
|
|
* Original Xvnc (C) 1999 AT&T Laboratories Cambridge.
|
|
|
|
@ -10,33 +11,56 @@
|
|
|
|
|
* see GPL (latest version) for full details
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifdef __STRICT_ANSI__
|
|
|
|
|
#define _BSD_SOURCE
|
|
|
|
|
#endif
|
|
|
|
|
#include <rfb/rfb.h>
|
|
|
|
|
#include <rfb/rfbregion.h>
|
|
|
|
|
#include "private.h"
|
|
|
|
|
extern "C" {
|
|
|
|
|
#ifdef __STRICT_ANSI__
|
|
|
|
|
#define _BSD_SOURCE
|
|
|
|
|
#endif
|
|
|
|
|
#include <rfb/rfb.h>
|
|
|
|
|
#include <rfb/rfbregion.h>
|
|
|
|
|
#include "private.h"
|
|
|
|
|
|
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
|
|
#ifndef false
|
|
|
|
|
#define false 0
|
|
|
|
|
#define true -1
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef LIBVNCSERVER_HAVE_SYS_TYPES_H
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifndef WIN32
|
|
|
|
|
#include <sys/socket.h>
|
|
|
|
|
#include <netinet/in.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include <signal.h>
|
|
|
|
|
#include <time.h>
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
#include <ntqobject.h>
|
|
|
|
|
#include <ntqvariant.h>
|
|
|
|
|
#include <ntqtimer.h>
|
|
|
|
|
#include <ntqthread.h>
|
|
|
|
|
|
|
|
|
|
#ifndef false
|
|
|
|
|
#define false 0
|
|
|
|
|
#define true -1
|
|
|
|
|
#endif
|
|
|
|
|
#include "main.h"
|
|
|
|
|
|
|
|
|
|
#ifdef LIBVNCSERVER_HAVE_SYS_TYPES_H
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
#endif
|
|
|
|
|
ControlPipeHandlerObject* mControlPipeHandler = NULL;
|
|
|
|
|
TQEventLoopThread* mControlPipeHandlerThread = NULL;
|
|
|
|
|
|
|
|
|
|
#ifndef WIN32
|
|
|
|
|
#include <sys/socket.h>
|
|
|
|
|
#include <netinet/in.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#endif
|
|
|
|
|
OnHoldClientHandlerObject* mOnHoldClientHandler = NULL;
|
|
|
|
|
TQEventLoopThread* mOnHoldClientHandlerThread = NULL;
|
|
|
|
|
|
|
|
|
|
#include <signal.h>
|
|
|
|
|
#include <time.h>
|
|
|
|
|
extern "C" {
|
|
|
|
|
/* from scale.c */
|
|
|
|
|
void rfbScaledScreenUpdate(rfbScreenInfoPtr screen, int x1, int y1, int x2, int y2);
|
|
|
|
|
|
|
|
|
|
/* from rfbserver.c */
|
|
|
|
|
rfbClientIteratorPtr rfbGetClientIteratorWithClosed(rfbScreenInfoPtr rfbScreen);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int extMutex_initialized = 0;
|
|
|
|
|
static int logMutex_initialized = 0;
|
|
|
|
@ -169,7 +193,7 @@ rfbBool rfbEnableExtension(rfbClientPtr cl, rfbProtocolExtension* extension,
|
|
|
|
|
if(extData->extension == extension)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
extData = calloc(sizeof(rfbExtensionData),1);
|
|
|
|
|
extData = (rfbExtensionData*)calloc(sizeof(rfbExtensionData),1);
|
|
|
|
|
extData->extension = extension;
|
|
|
|
|
extData->data = data;
|
|
|
|
|
extData->next = cl->extensions;
|
|
|
|
@ -445,6 +469,7 @@ clientOutput(void *data)
|
|
|
|
|
rfbClientPtr cl = (rfbClientPtr)data;
|
|
|
|
|
rfbBool haveUpdate;
|
|
|
|
|
sraRegion* updateRegion;
|
|
|
|
|
cl->onHold = FALSE;
|
|
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
|
haveUpdate = false;
|
|
|
|
@ -453,7 +478,7 @@ clientOutput(void *data)
|
|
|
|
|
/* Client has disconnected. */
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
if (cl->state != RFB_NORMAL || cl->onHold) {
|
|
|
|
|
if (cl->state != _rfbClientRec::RFB_NORMAL || cl->onHold) {
|
|
|
|
|
/* just sleep until things get normal */
|
|
|
|
|
usleep(cl->screen->deferUpdateTime * 1000);
|
|
|
|
|
continue;
|
|
|
|
@ -509,8 +534,13 @@ static void *
|
|
|
|
|
clientInput(void *data)
|
|
|
|
|
{
|
|
|
|
|
rfbClientPtr cl = (rfbClientPtr)data;
|
|
|
|
|
pthread_t output_thread;
|
|
|
|
|
pthread_create(&output_thread, NULL, clientOutput, (void *)cl);
|
|
|
|
|
/* Start output thread */
|
|
|
|
|
TQEventLoopThread* clientOutputHandlerThread = new TQEventLoopThread();
|
|
|
|
|
ClientOutputHandlerObject* clientOutputHandler = new ClientOutputHandlerObject();
|
|
|
|
|
clientOutputHandler->d = cl;
|
|
|
|
|
clientOutputHandler->moveToThread(clientOutputHandlerThread);
|
|
|
|
|
TQTimer::singleShot(0, clientOutputHandler, SLOT(run()));
|
|
|
|
|
clientOutputHandlerThread->start();
|
|
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
|
fd_set rfds, wfds, efds;
|
|
|
|
@ -557,7 +587,11 @@ clientInput(void *data)
|
|
|
|
|
LOCK(cl->updateMutex);
|
|
|
|
|
TSIGNAL(cl->updateCond);
|
|
|
|
|
UNLOCK(cl->updateMutex);
|
|
|
|
|
IF_PTHREADS(pthread_join(output_thread, NULL));
|
|
|
|
|
clientOutputHandlerThread->wait();
|
|
|
|
|
delete clientOutputHandlerThread;
|
|
|
|
|
clientOutputHandlerThread = NULL;
|
|
|
|
|
delete clientOutputHandler;
|
|
|
|
|
clientOutputHandler = NULL;
|
|
|
|
|
|
|
|
|
|
rfbClientConnectionGone(cl);
|
|
|
|
|
|
|
|
|
@ -574,6 +608,15 @@ listenerRun(void *data)
|
|
|
|
|
socklen_t len;
|
|
|
|
|
fd_set listen_fds; /* temp file descriptor list for select() */
|
|
|
|
|
|
|
|
|
|
if (screen->inetdSock != -1) {
|
|
|
|
|
cl = rfbNewClient(screen, screen->inetdSock);
|
|
|
|
|
if (cl && !cl->onHold)
|
|
|
|
|
rfbStartOnHoldClient(cl);
|
|
|
|
|
else if (screen->inetdDisconnectHook && !cl)
|
|
|
|
|
screen->inetdDisconnectHook();
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* TODO: this thread wont die by restarting the server */
|
|
|
|
|
/* TODO: HTTP is not handled */
|
|
|
|
|
while (1) {
|
|
|
|
@ -607,7 +650,12 @@ listenerRun(void *data)
|
|
|
|
|
void
|
|
|
|
|
rfbStartOnHoldClient(rfbClientPtr cl)
|
|
|
|
|
{
|
|
|
|
|
pthread_create(&cl->client_thread, NULL, clientInput, (void *)cl);
|
|
|
|
|
mOnHoldClientHandlerThread = new TQEventLoopThread();
|
|
|
|
|
mOnHoldClientHandler = new OnHoldClientHandlerObject();
|
|
|
|
|
mOnHoldClientHandler->d = cl;
|
|
|
|
|
mOnHoldClientHandler->moveToThread(mOnHoldClientHandlerThread);
|
|
|
|
|
TQTimer::singleShot(0, mOnHoldClientHandler, SLOT(run()));
|
|
|
|
|
mOnHoldClientHandlerThread->start();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#else
|
|
|
|
@ -702,7 +750,7 @@ static rfbCursorPtr rfbDefaultGetCursorPtr(rfbClientPtr cl)
|
|
|
|
|
static rfbBool rfbDefaultPasswordCheck(rfbClientPtr cl,const char* response,int len)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
char *passwd=rfbDecryptPasswdFromFile(cl->screen->authPasswdData);
|
|
|
|
|
char *passwd=rfbDecryptPasswdFromFile((char*)cl->screen->authPasswdData);
|
|
|
|
|
|
|
|
|
|
if(!passwd) {
|
|
|
|
|
rfbErr("Couldn't read password file: %s\n",cl->screen->authPasswdData);
|
|
|
|
@ -810,7 +858,7 @@ rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,
|
|
|
|
|
int width,int height,int bitsPerSample,int samplesPerPixel,
|
|
|
|
|
int bytesPerPixel)
|
|
|
|
|
{
|
|
|
|
|
rfbScreenInfoPtr screen=calloc(sizeof(rfbScreenInfo),1);
|
|
|
|
|
rfbScreenInfoPtr screen=(rfbScreenInfoPtr)calloc(sizeof(rfbScreenInfo),1);
|
|
|
|
|
|
|
|
|
|
if (! logMutex_initialized) {
|
|
|
|
|
INIT_MUTEX(logMutex);
|
|
|
|
@ -919,6 +967,7 @@ rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,
|
|
|
|
|
screen->setTranslateFunction = rfbSetTranslateFunction;
|
|
|
|
|
screen->newClientHook = rfbDefaultNewClientHook;
|
|
|
|
|
screen->displayHook = NULL;
|
|
|
|
|
screen->inetdDisconnectHook = NULL;
|
|
|
|
|
screen->displayFinishedHook = NULL;
|
|
|
|
|
screen->getKeyboardLedStateHook = NULL;
|
|
|
|
|
screen->xvpHook = NULL;
|
|
|
|
@ -1015,7 +1064,22 @@ void rfbScreenCleanup(rfbScreenInfoPtr screen)
|
|
|
|
|
cl1=cl;
|
|
|
|
|
}
|
|
|
|
|
rfbReleaseClientIterator(i);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mOnHoldClientHandlerThread) {
|
|
|
|
|
mOnHoldClientHandlerThread->exit();
|
|
|
|
|
delete mOnHoldClientHandlerThread;
|
|
|
|
|
mOnHoldClientHandlerThread = NULL;
|
|
|
|
|
delete mOnHoldClientHandler;
|
|
|
|
|
mOnHoldClientHandler = NULL;
|
|
|
|
|
}
|
|
|
|
|
if (mControlPipeHandlerThread) {
|
|
|
|
|
mControlPipeHandlerThread->exit();
|
|
|
|
|
delete mControlPipeHandlerThread;
|
|
|
|
|
mControlPipeHandlerThread = NULL;
|
|
|
|
|
delete mControlPipeHandler;
|
|
|
|
|
mControlPipeHandler = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define FREE_IF(x) if(screen->x) free(screen->x)
|
|
|
|
|
FREE_IF(colourMap.data.bytes);
|
|
|
|
|
FREE_IF(underCursorBuffer);
|
|
|
|
@ -1180,12 +1244,15 @@ void rfbRunEventLoop(rfbScreenInfoPtr screen, long usec, rfbBool runInBackground
|
|
|
|
|
{
|
|
|
|
|
if(runInBackground) {
|
|
|
|
|
#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
|
|
|
|
|
pthread_t listener_thread;
|
|
|
|
|
|
|
|
|
|
screen->backgroundLoop = TRUE;
|
|
|
|
|
|
|
|
|
|
pthread_create(&listener_thread, NULL, listenerRun, screen);
|
|
|
|
|
return;
|
|
|
|
|
screen->backgroundLoop = TRUE;
|
|
|
|
|
|
|
|
|
|
mControlPipeHandlerThread = new TQEventLoopThread();
|
|
|
|
|
mControlPipeHandler = new ControlPipeHandlerObject();
|
|
|
|
|
mControlPipeHandler->d = screen;
|
|
|
|
|
mControlPipeHandler->moveToThread(mControlPipeHandlerThread);
|
|
|
|
|
TQTimer::singleShot(0, mControlPipeHandler, SLOT(run()));
|
|
|
|
|
mControlPipeHandlerThread->start();
|
|
|
|
|
return;
|
|
|
|
|
#else
|
|
|
|
|
rfbErr("Can't run in background, because I don't have PThreads!\n");
|
|
|
|
|
return;
|
|
|
|
@ -1198,3 +1265,50 @@ void rfbRunEventLoop(rfbScreenInfoPtr screen, long usec, rfbBool runInBackground
|
|
|
|
|
while(rfbIsActive(screen))
|
|
|
|
|
rfbProcessEvents(screen,usec);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ControlPipeHandlerObject::ControlPipeHandlerObject() : TQObject() {
|
|
|
|
|
//
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ControlPipeHandlerObject::~ControlPipeHandlerObject() {
|
|
|
|
|
//
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ControlPipeHandlerObject::run(void) {
|
|
|
|
|
listenerRun(d);
|
|
|
|
|
|
|
|
|
|
// Terminate thread
|
|
|
|
|
TQThread::exit();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OnHoldClientHandlerObject::OnHoldClientHandlerObject() : TQObject() {
|
|
|
|
|
//
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OnHoldClientHandlerObject::~OnHoldClientHandlerObject() {
|
|
|
|
|
//
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OnHoldClientHandlerObject::run(void) {
|
|
|
|
|
clientInput(d);
|
|
|
|
|
|
|
|
|
|
// Terminate thread
|
|
|
|
|
TQThread::exit();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ClientOutputHandlerObject::ClientOutputHandlerObject() : TQObject() {
|
|
|
|
|
//
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ClientOutputHandlerObject::~ClientOutputHandlerObject() {
|
|
|
|
|
//
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ClientOutputHandlerObject::run(void) {
|
|
|
|
|
clientOutput(d);
|
|
|
|
|
|
|
|
|
|
// Terminate thread
|
|
|
|
|
TQThread::exit();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#include "main.moc"
|