From 366c7e7c2122cc4271a2dd65d270ac4175edd5e4 Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Sat, 10 Jan 2015 20:19:00 -0600 Subject: [PATCH] Port required changes for TDE's krfb server from the old libvnc version embedded with krfb --- AUTHORS | 1 + CMakeLists.txt | 125 ++++---------------------- libvncserver/main.c | 188 +++++++++++++++++++++++++++++++-------- libvncserver/rfbserver.c | 11 +++ rfb/rfb.h | 10 +++ rfb/rfbproto.h | 8 ++ 6 files changed, 198 insertions(+), 145 deletions(-) diff --git a/AUTHORS b/AUTHORS index a91ccfa..092ef2b 100644 --- a/AUTHORS +++ b/AUTHORS @@ -40,6 +40,7 @@ Rostislav Lisovy, Oliver Loch, Raphael Kubo da Costa, Amandeep Singh, Brian Bidulock, Daniel Cohen Gindi, David Verbeiren, Luca Falavigna, Matthias Treydte, Nicolas Ruff, Robbert Klarenbeek and Floris Bos. +Modified version for TDE's krfb/krdc applications created and maintained by Timothy Pearson. Probably I forgot quite a few people sending a patch here and there, which really made a difference. Without those, some obscure bugs still would diff --git a/CMakeLists.txt b/CMakeLists.txt index 269805f..a437171 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -104,11 +104,11 @@ if(GNUTLS_FOUND) set(LIBVNCSERVER_WITH_CLIENT_TLS 1) option(LIBVNCSERVER_WITH_WEBSOCKETS "Build with websockets support (gnutls)" ON) set(WEBSOCKET_LIBRARIES ${RESOLV_LIB} ${GNUTLS_LIBRARIES}) - set(WSSRCS ${LIBVNCSERVER_DIR}/rfbssl_gnutls ${LIBVNCSERVER_DIR}/rfbcrypto_gnutls) + set(WSSRCS ${LIBVNCSERVER_DIR}/rfbssl_gnutls.c ${LIBVNCSERVER_DIR}/rfbcrypto_gnutls.c) elseif(OPENSSL_FOUND) option(LIBVNCSERVER_WITH_WEBSOCKETS "Build with websockets support (openssl)" ON) set(WEBSOCKET_LIBRARIES ${RESOLV_LIB} ${OPENSSL_LIBRARIES}) - set(WSSRCS ${LIBVNCSERVER_DIR}/rfbssl_openssl ${LIBVNCSERVER_DIR}/rfbcrypto_openssl) + set(WSSRCS ${LIBVNCSERVER_DIR}/rfbssl_openssl.c ${LIBVNCSERVER_DIR}/rfbcrypto_openssl.c) else() option(LIBVNCSERVER_WITH_WEBSOCKETS "Build with websockets support (no ssl)" ON) set(WEBSOCKET_LIBRARIES ${RESOLV_LIB}) @@ -167,11 +167,11 @@ TEST_BIG_ENDIAN(LIBVNCSERVER_WORDS_BIGENDIAN) # LIBVNCSERVER_ENOENT_WORKAROUND # inline -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/rfb/rfbconfig.h.cmake ${CMAKE_BINARY_DIR}/rfb/rfbconfig.h) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/rfb/rfbint.h.cmake ${CMAKE_BINARY_DIR}/rfb/rfbint.h) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/rfb/rfbconfig.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/rfb/rfbconfig.h) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/rfb/rfbint.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/rfb/rfbint.h) set(LIBVNCSERVER_SOURCES - ${LIBVNCSERVER_DIR}/main.c + ${LIBVNCSERVER_DIR}/main.cc ${LIBVNCSERVER_DIR}/rfbserver.c ${LIBVNCSERVER_DIR}/rfbregion.c ${LIBVNCSERVER_DIR}/auth.c @@ -269,111 +269,20 @@ if(LIBVNCSERVER_WITH_WEBSOCKETS) ) endif(LIBVNCSERVER_WITH_WEBSOCKETS) +##### tdevncclient (static) ######################## -add_library(vncclient SHARED ${LIBVNCCLIENT_SOURCES}) -add_library(vncserver SHARED ${LIBVNCSERVER_SOURCES}) -if(WIN32) - set(ADDITIONAL_LIBS ${ADDITIONAL_LIBS} ws2_32) -endif(WIN32) - -target_link_libraries(vncclient - ${ADDITIONAL_LIBS} - ${ZLIB_LIBRARIES} - ${JPEG_LIBRARIES} - ${GNUTLS_LIBRARIES} -) -target_link_libraries(vncserver - ${ADDITIONAL_LIBS} - ${ZLIB_LIBRARIES} - ${JPEG_LIBRARIES} - ${PNG_LIBRARIES} - ${WEBSOCKET_LIBRARIES} -) - -SET_TARGET_PROPERTIES(vncclient vncserver - PROPERTIES SOVERSION "0.0.0" -) - -# tests -set(LIBVNCSERVER_TESTS - backchannel - camera - colourmaptest - example - fontsel - pnmshow - pnmshow24 - regiontest - rotate - simple - simple15 - storepasswd - vncev - ) - -if(Threads_FOUND) - set(LIBVNCSERVER_TESTS - ${LIBVNCSERVER_TESTS} - blooptest - ) -endif(Threads_FOUND) - -if(TIGHTVNC_FILETRANSFER) - set(LIBVNCSERVER_TESTS - ${LIBVNCSERVER_TESTS} - filetransfer - ) -endif(TIGHTVNC_FILETRANSFER) - -if(MACOS) - set(LIBVNCSERVER_TESTS - ${LIBVNCSERVER_TESTS} - mac - ) -endif(MACOS) - -set(LIBVNCCLIENT_TESTS - backchannel - ppmtest +tde_add_library( tdevncclient STATIC_PIC AUTOMOC + SOURCES + ${LIBVNCCLIENT_SOURCES} + LINK + ${ADDITIONAL_LIBS} ${ZLIB_LIBRARIES} ${JPEG_LIBRARIES} ${GNUTLS_LIBRARIES} ) -if(SDL_FOUND) - include_directories(${SDL_INCLUDE_DIR}) - set(LIBVNCCLIENT_TESTS - ${LIBVNCCLIENT_TESTS} - SDLvncviewer - ) - set(SDLvncviewer_EXTRA_SOURCES scrap.c) -endif(SDL_FOUND) +##### tdevncserver (static) ######################## -if(HAVE_FFMPEG) - set(LIBVNCCLIENT_TESTS - ${LIBVNCCLIENT_TESTS} - vnc2mpg - ) -endif(HAVE_FFMPEG) - - -file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/examples) -foreach(test ${LIBVNCSERVER_TESTS}) - add_executable(examples/${test} ${LIBVNCSRVTEST_DIR}/${test}.c) - target_link_libraries(examples/${test} vncserver ${CMAKE_THREAD_LIBS_INIT}) -endforeach(test ${LIBVNCSERVER_TESTS}) - -file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/client_examples) -foreach(test ${LIBVNCCLIENT_TESTS}) - add_executable(client_examples/${test} ${LIBVNCCLITEST_DIR}/${test}.c ${LIBVNCCLITEST_DIR}/${${test}_EXTRA_SOURCES} ) - target_link_libraries(client_examples/${test} vncclient ${CMAKE_THREAD_LIBS_INIT} ${X11_LIBRARIES} ${SDL_LIBRARY} ${FFMPEG_LIBRARIES}) -endforeach(test ${LIBVNCCLIENT_TESTS}) - -install_targets(/lib vncserver) -install_targets(/lib vncclient) -install_files(/include/rfb FILES - rfb/keysym.h - rfb/rfb.h - rfb/rfbclient.h - rfb/rfbconfig.h - rfb/rfbint.h - rfb/rfbproto.h - rfb/rfbregion.h +tde_add_library( tdevncserver STATIC_PIC AUTOMOC + SOURCES + ${LIBVNCSERVER_SOURCES} + LINK + ${ADDITIONAL_LIBS} ${ZLIB_LIBRARIES} ${JPEG_LIBRARIES} ${PNG_LIBRARIES} ${WEBSOCKET_LIBRARIES} ) diff --git a/libvncserver/main.c b/libvncserver/main.c index 9839c85..cb66976 100644 --- a/libvncserver/main.c +++ b/libvncserver/main.c @@ -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 . * LibVNCServer (C) 2001 Johannes E. Schindelin * Original OSXvnc (C) 2001 Dan McGuirk . * 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 -#include -#include "private.h" +extern "C" { + #ifdef __STRICT_ANSI__ + #define _BSD_SOURCE + #endif + #include + #include + #include "private.h" + + #include + #include + + #ifndef false + #define false 0 + #define true -1 + #endif + + #ifdef LIBVNCSERVER_HAVE_SYS_TYPES_H + #include + #endif + + #ifndef WIN32 + #include + #include + #include + #endif + + #include + #include +} -#include -#include +#include +#include +#include +#include -#ifndef false -#define false 0 -#define true -1 -#endif +#include "main.h" -#ifdef LIBVNCSERVER_HAVE_SYS_TYPES_H -#include -#endif +ControlPipeHandlerObject* mControlPipeHandler = NULL; +TQEventLoopThread* mControlPipeHandlerThread = NULL; -#ifndef WIN32 -#include -#include -#include -#endif +OnHoldClientHandlerObject* mOnHoldClientHandler = NULL; +TQEventLoopThread* mOnHoldClientHandlerThread = NULL; -#include -#include +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" \ No newline at end of file diff --git a/libvncserver/rfbserver.c b/libvncserver/rfbserver.c index cab0018..fbae203 100644 --- a/libvncserver/rfbserver.c +++ b/libvncserver/rfbserver.c @@ -3,6 +3,7 @@ */ /* + * Copyright (C) 2015 Timothy Pearson . * Copyright (C) 2011-2012 D. R. Commander * Copyright (C) 2005 Rohit Kumar, Johannes E. Schindelin * Copyright (C) 2002 RealVNC Ltd. @@ -328,6 +329,7 @@ rfbNewTCPOrUDPClient(rfbScreenInfoPtr rfbScreen, cl->clientData = NULL; cl->clientGoneHook = rfbDoNothingWithClient; + cl->negotiationFinishedHook = rfbDoNothingWithClient; if(isUDP) { rfbLog(" accepted UDP client\n"); @@ -434,6 +436,7 @@ rfbNewTCPOrUDPClient(rfbScreenInfoPtr rfbScreen, cl->enableCursorPosUpdates = FALSE; cl->useRichCursorEncoding = FALSE; cl->enableLastRectEncoding = FALSE; + cl->disableBackground = FALSE; cl->enableKeyboardLedState = FALSE; cl->enableSupportedMessages = FALSE; cl->enableSupportedEncodings = FALSE; @@ -2093,6 +2096,7 @@ rfbProcessClientNormalMessage(rfbClientPtr cl) cl->enableCursorShapeUpdates = FALSE; cl->enableCursorShapeUpdates = FALSE; cl->enableLastRectEncoding = FALSE; + cl->disableBackground = FALSE; cl->enableKeyboardLedState = FALSE; cl->enableSupportedMessages = FALSE; cl->enableSupportedEncodings = FALSE; @@ -2181,6 +2185,11 @@ rfbProcessClientNormalMessage(rfbClientPtr cl) cl->enableLastRectEncoding = TRUE; } break; + case rfbEncodingBackground: + rfbLog("Disabling background for client " + "%s\n", cl->host); + cl->disableBackground = TRUE; + break; case rfbEncodingNewFBSize: if (!cl->useNewFBSize) { rfbLog("Enabling NewFBSize protocol extension for client " @@ -2335,6 +2344,8 @@ rfbProcessClientNormalMessage(rfbClientPtr cl) cl->enableCursorPosUpdates = FALSE; } + cl->negotiationFinishedHook(cl); + return; } diff --git a/rfb/rfb.h b/rfb/rfb.h index f7919c6..59ff4fa 100644 --- a/rfb/rfb.h +++ b/rfb/rfb.h @@ -10,6 +10,7 @@ */ /* + * Copyright (C) 2015 Timothy Pearson . * Copyright (C) 2005 Rohit Kumar , * Johannes E. Schindelin * Copyright (C) 2002 RealVNC Ltd. @@ -149,6 +150,7 @@ typedef rfbBool (*rfbSetTranslateFunctionProcPtr)(struct _rfbClientRec* cl); typedef rfbBool (*rfbPasswordCheckProcPtr)(struct _rfbClientRec* cl,const char* encryptedPassWord,int len); typedef enum rfbNewClientAction (*rfbNewClientHookPtr)(struct _rfbClientRec* cl); typedef void (*rfbDisplayHookPtr)(struct _rfbClientRec* cl); +typedef void (*rfbInetdDisconnectPtr)(); typedef void (*rfbDisplayFinishedHookPtr)(struct _rfbClientRec* cl, int result); /** support the capability to view the caps/num/scroll states of the X server */ typedef int (*rfbGetKeyboardLedStateHookPtr)(struct _rfbScreenInfo* screen); @@ -340,6 +342,9 @@ typedef struct _rfbScreenInfo rfbNewClientHookPtr newClientHook; /** displayHook is called just before a frame buffer update */ rfbDisplayHookPtr displayHook; + /* inetdDisconnectHook is called when the connection has been + interrupted before a client could connect. */ + rfbInetdDisconnectPtr inetdDisconnectHook; /** These hooks are called to pass keyboard state back to the client */ rfbGetKeyboardLedStateHookPtr getKeyboardLedStateHook; @@ -413,6 +418,7 @@ typedef struct sraRegion* sraRegionPtr; */ typedef void (*ClientGoneHookPtr)(struct _rfbClientRec* cl); +typedef void (*NegotiationFinishedHookPtr)(struct _rfbClientRec* cl); typedef struct _rfbFileTransferData { int fd; @@ -458,6 +464,9 @@ typedef struct _rfbClientRec { void* clientData; ClientGoneHookPtr clientGoneHook; + /* negotiationFinishedHook is called when the negotiation phase has ended */ + NegotiationFinishedHookPtr negotiationFinishedHook; + SOCKET sock; char *host; @@ -623,6 +632,7 @@ typedef struct _rfbClientRec { rfbBool enableServerIdentity; /**< client supports ServerIdentity encoding */ rfbBool enableKeyboardLedState; /**< client supports KeyboardState encoding */ rfbBool enableLastRectEncoding; /**< client supports LastRect encoding */ + rfbBool disableBackground; /**< client wants to disable background */ rfbBool enableCursorShapeUpdates; /**< client supports cursor shape updates */ rfbBool enableCursorPosUpdates; /**< client supports cursor position updates */ rfbBool useRichCursorEncoding; /**< rfbEncodingRichCursor is preferred */ diff --git a/rfb/rfbproto.h b/rfb/rfbproto.h index 4169fd6..4baae6d 100644 --- a/rfb/rfbproto.h +++ b/rfb/rfbproto.h @@ -13,6 +13,7 @@ */ /* + * Copyright (C) 2015 Timothy Pearson . All Rights Reserved. * Copyright (C) 2009-2010 D. R. Commander. All Rights Reserved. * Copyright (C) 2005 Rohit Kumar, Johannes E. Schindelin * Copyright (C) 2004-2008 Sun Microsystems, Inc. All Rights Reserved. @@ -448,6 +449,13 @@ typedef struct { #define rfbEncodingH264 0x48323634 +/* + * Reserved range for TDE: + * 0xFFFE0100 - 0xFFFE01FF + */ + +#define rfbEncodingBackground 0xFFFE0125 + /* Cache & XOR-Zlib - rdv@2002 */ #define rfbEncodingCache 0xFFFF0000 #define rfbEncodingCacheEnable 0xFFFF0001