Dynamically load libvnc at runtime

This commit is contained in:
hax0kartik 2020-04-14 02:46:01 +05:30
parent 1c4e4abbab
commit 640dfdd4a0
2 changed files with 42 additions and 13 deletions

View File

@ -684,7 +684,7 @@ if(NOT ZM_NO_LIBVNC)
find_library(LIBVNC_LIBRARIES vncclient) find_library(LIBVNC_LIBRARIES vncclient)
if(LIBVNC_LIBRARIES) if(LIBVNC_LIBRARIES)
set(HAVE_LIBVNC 1) set(HAVE_LIBVNC 1)
list(APPEND ZM_BIN_LIBS "${LIBVNC_LIBRARIES}") # list(APPEND ZM_BIN_LIBS "${LIBVNC_LIBRARIES}")
find_path(LIBVNC_INCLUDE_DIR "rfb/rfb.h") find_path(LIBVNC_INCLUDE_DIR "rfb/rfb.h")
if(LIBVNC_INCLUDE_DIR) if(LIBVNC_INCLUDE_DIR)
include_directories("${LIBVNC_INCLUDE_DIR}") include_directories("${LIBVNC_INCLUDE_DIR}")

View File

@ -1,3 +1,4 @@
#include <dlfcn.h>
#include "zm.h" #include "zm.h"
#include "zm_signal.h" #include "zm_signal.h"
#include "zm_libvnc_camera.h" #include "zm_libvnc_camera.h"
@ -8,14 +9,41 @@
static int TAG_0; static int TAG_0;
static int TAG_1; static int TAG_1;
static int TAG_2; static int TAG_2;
static void *libvnc_lib = nullptr;
static void *(*rfbClientGetClientData_f)(rfbClient*, void*) = nullptr;
static rfbClient *(*rfbGetClient_f)(int, int, int) = nullptr;
static void (*rfbClientSetClientData_f)(rfbClient*, void*, void*) = nullptr;
static rfbBool (*rfbInitClient_f)(rfbClient*, int*, char**) = nullptr;
static void (*rfbClientCleanup_f)(rfbClient*) = nullptr;
static int (*WaitForMessage_f)(rfbClient*, unsigned int) = nullptr;
static rfbBool (*HandleRFBServerMessage_f)(rfbClient*) = nullptr;
void bind_libvnc_symbols() {
if(libvnc_lib != nullptr) // Safe-check
return;
libvnc_lib = dlopen("libvncclient.so", RTLD_LAZY | RTLD_GLOBAL);
if(!libvnc_lib){
Error("Error loading libvlc: %s", dlerror());
return;
}
*(void**) (&rfbClientGetClientData_f) = dlsym(libvnc_lib, "rfbClientGetClientData");
*(void**) (&rfbGetClient_f) = dlsym(libvnc_lib, "rfbGetClient");
*(void**) (&rfbClientSetClientData_f) = dlsym(libvnc_lib, "rfbClientSetClientData");
*(void**) (&rfbInitClient_f) = dlsym(libvnc_lib, "rfbInitClient");
*(void**) (&rfbClientCleanup_f) = dlsym(libvnc_lib, "rfbClientCleanup");
*(void**) (&WaitForMessage_f) = dlsym(libvnc_lib, "WaitForMessage");
*(void**) (&HandleRFBServerMessage_f) = dlsym(libvnc_lib, "HandleRFBServerMessage");
}
static void GotFrameBufferUpdateCallback(rfbClient *rfb, int x, int y, int w, int h){ static void GotFrameBufferUpdateCallback(rfbClient *rfb, int x, int y, int w, int h){
VncPrivateData *data = (VncPrivateData *)rfbClientGetClientData(rfb, &TAG_0); VncPrivateData *data = (VncPrivateData *)(*rfbClientGetClientData_f)(rfb, &TAG_0);
data->buffer = rfb->frameBuffer; data->buffer = rfb->frameBuffer;
} }
static char* GetPasswordCallback(rfbClient* cl){ static char* GetPasswordCallback(rfbClient* cl){
return strdup((const char *)rfbClientGetClientData(cl, &TAG_1)); return strdup((const char *)(*rfbClientGetClientData_f)(cl, &TAG_1));
} }
static rfbCredential* GetCredentialsCallback(rfbClient* cl, int credentialType){ static rfbCredential* GetCredentialsCallback(rfbClient* cl, int credentialType){
@ -25,8 +53,8 @@ static rfbCredential* GetCredentialsCallback(rfbClient* cl, int credentialType){
return NULL; return NULL;
} }
c->userCredential.password = strdup((const char *)rfbClientGetClientData(cl, &TAG_1)); c->userCredential.password = strdup((const char *)(*rfbClientGetClientData_f)(cl, &TAG_1));
c->userCredential.username = strdup((const char *)rfbClientGetClientData(cl, &TAG_2)); c->userCredential.username = strdup((const char *)(*rfbClientGetClientData_f)(cl, &TAG_2));
return c; return c;
} }
@ -94,11 +122,12 @@ VncCamera::~VncCamera() {
void VncCamera::Initialise() { void VncCamera::Initialise() {
Debug(2, "Initializing Client"); Debug(2, "Initializing Client");
mRfb = rfbGetClient(8, 3, 4); bind_libvnc_symbols();
mRfb = (*rfbGetClient_f)(8, 3, 4);
rfbClientSetClientData(mRfb, &TAG_0, &mVncData); (*rfbClientSetClientData_f)(mRfb, &TAG_0, &mVncData);
rfbClientSetClientData(mRfb, &TAG_1, (void *)mPass.c_str()); (*rfbClientSetClientData_f)(mRfb, &TAG_1, (void *)mPass.c_str());
rfbClientSetClientData(mRfb, &TAG_2, (void *)mUser.c_str()); (*rfbClientSetClientData_f)(mRfb, &TAG_2, (void *)mUser.c_str());
mRfb->GotFrameBufferUpdate = GotFrameBufferUpdateCallback; mRfb->GotFrameBufferUpdate = GotFrameBufferUpdateCallback;
mRfb->GetPassword = GetPasswordCallback; mRfb->GetPassword = GetPasswordCallback;
@ -107,14 +136,14 @@ void VncCamera::Initialise() {
mRfb->programName = "Zoneminder VNC Monitor"; mRfb->programName = "Zoneminder VNC Monitor";
mRfb->serverHost = strdup(mHost.c_str()); mRfb->serverHost = strdup(mHost.c_str());
mRfb->serverPort = atoi(mPort.c_str()); mRfb->serverPort = atoi(mPort.c_str());
rfbInitClient(mRfb, 0, nullptr); (*rfbInitClient_f)(mRfb, 0, nullptr);
scale.init(); scale.init();
} }
void VncCamera::Terminate() { void VncCamera::Terminate() {
if(mRfb->frameBuffer) if(mRfb->frameBuffer)
free(mRfb->frameBuffer); free(mRfb->frameBuffer);
rfbClientCleanup(mRfb); (*rfbClientCleanup_f)(mRfb);
return; return;
} }
@ -125,8 +154,8 @@ int VncCamera::PrimeCapture() {
int VncCamera::PreCapture() { int VncCamera::PreCapture() {
Debug(2, "PreCapture"); Debug(2, "PreCapture");
WaitForMessage(mRfb, 500); (*WaitForMessage_f)(mRfb, 500);
rfbBool res = HandleRFBServerMessage(mRfb); rfbBool res = (*HandleRFBServerMessage_f)(mRfb);
return res == TRUE ? 1 : -1 ; return res == TRUE ? 1 : -1 ;
} }