From 64f57aa373b6bf40470fd9b4f8255a52444896dc Mon Sep 17 00:00:00 2001 From: hax0kartik Date: Wed, 8 Apr 2020 05:18:16 -0400 Subject: [PATCH] Dynamically load libcurl at runtime --- CMakeLists.txt | 2 +- src/zm_curl_camera.cpp | 88 +++++++++++++++++++++++++++--------------- src/zm_curl_camera.h | 12 ++++++ 3 files changed, 70 insertions(+), 32 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9694407a3..eccb42c17 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -322,7 +322,7 @@ if(NOT ZM_NO_CURL) find_package(CURL) if(CURL_FOUND) set(HAVE_LIBCURL 1) - list(APPEND ZM_BIN_LIBS ${CURL_LIBRARIES}) + #list(APPEND ZM_BIN_LIBS ${CURL_LIBRARIES}) include_directories(${CURL_INCLUDE_DIRS}) set(CMAKE_REQUIRED_INCLUDES ${CURL_INCLUDE_DIRS}) check_include_file("curl/curl.h" HAVE_CURL_CURL_H) diff --git a/src/zm_curl_camera.cpp b/src/zm_curl_camera.cpp index 1f3a6a54b..df8a1f26f 100644 --- a/src/zm_curl_camera.cpp +++ b/src/zm_curl_camera.cpp @@ -15,8 +15,9 @@ // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// +// +#include #include "zm.h" #include "zm_curl_camera.h" @@ -55,14 +56,36 @@ void cURLCamera::Initialise() { content_type_match_len = strlen(content_type_match); databuffer.expand(CURL_BUFFER_INITIAL_SIZE); + + void *curl_lib = dlopen("libcurl.so", 0); + if (!curl_lib) + curl_lib = dlopen("libcurl.so.3", 0); + if (!curl_lib) + curl_lib = dlopen("libcurl.so.4", 0); + if (!curl_lib) + curl_lib = dlopen("libcurl-gnutls.so.4", 0); + if (!curl_lib) + Fatal("Could not load libcurl: ", dlerror()); + + // Load up all required symbols here + *(void**) (&curl_global_init_f) = dlsym(curl_lib, "curl_global_init"); + *(void**) (&curl_global_cleanup_f) = dlsym(curl_lib, "curl_global_cleanup"); + *(void**) (&curl_easy_strerror_f) = dlsym(curl_lib, "curl_easy_strerror"); + *(void**) (&curl_version_f) = dlsym(curl_lib, "curl_version"); + *(void**) (&curl_easy_init_f) = dlsym(curl_lib, "curl_easy_init"); + *(void**) (&curl_easy_getinfo_f) = dlsym(curl_lib, "curl_easy_getinfo"); + *(void**) (&curl_easy_perform_f) = dlsym(curl_lib, "curl_easy_perform"); + *(void**) (&curl_easy_setopt_f) = dlsym(curl_lib, "curl_easy_setopt"); + *(void**) (&curl_easy_cleanup_f) = dlsym(curl_lib, "curl_easy_cleanup"); /* cURL initialization */ - CURLcode cRet = curl_global_init(CURL_GLOBAL_ALL); + CURLcode cRet = (*curl_global_init_f)(CURL_GLOBAL_ALL); if(cRet != CURLE_OK) { - Fatal("libcurl initialization failed: ", curl_easy_strerror(cRet)); + Fatal("libcurl initialization failed: ", (*curl_easy_strerror_f)(cRet)); + dlclose(curl_lib); } - Debug(2,"libcurl version: %s",curl_version()); + Debug(2,"libcurl version: %s", (*curl_version_f)()); /* Create the shared data mutex */ int nRet = pthread_mutex_init(&shareddata_mutex, NULL); @@ -102,8 +125,10 @@ void cURLCamera::Terminate() { pthread_mutex_destroy(&shareddata_mutex); /* cURL cleanup */ - curl_global_cleanup(); + (*curl_global_cleanup_f)(); + if(curl_lib) + dlclose(curl_lib); } int cURLCamera::PrimeCapture() { @@ -376,58 +401,59 @@ void* cURLCamera::thread_func() { long tRet; double dSize; - c = curl_easy_init(); + c = (*curl_easy_init_f)(); if(c == NULL) { + dlclose(curl_lib); Fatal("Failed getting easy handle from libcurl"); } CURLcode cRet; /* Set URL */ - cRet = curl_easy_setopt(c, CURLOPT_URL, mPath.c_str()); + cRet = (*curl_easy_setopt_f)(c, CURLOPT_URL, mPath.c_str()); if(cRet != CURLE_OK) - Fatal("Failed setting libcurl URL: %s", curl_easy_strerror(cRet)); + Fatal("Failed setting libcurl URL: %s", *(curl_easy_strerror_f)(cRet)); /* Header callback */ - cRet = curl_easy_setopt(c, CURLOPT_HEADERFUNCTION, &header_callback_dispatcher); + cRet = (*curl_easy_setopt_f)(c, CURLOPT_HEADERFUNCTION, &header_callback_dispatcher); if(cRet != CURLE_OK) - Fatal("Failed setting libcurl header callback function: %s", curl_easy_strerror(cRet)); - cRet = curl_easy_setopt(c, CURLOPT_HEADERDATA, this); + Fatal("Failed setting libcurl header callback function: %s", (*curl_easy_strerror_f)(cRet)); + cRet = (*curl_easy_setopt_f)(c, CURLOPT_HEADERDATA, this); if(cRet != CURLE_OK) - Fatal("Failed setting libcurl header callback object: %s", curl_easy_strerror(cRet)); + Fatal("Failed setting libcurl header callback object: %s", (*curl_easy_strerror_f)(cRet)); /* Data callback */ - cRet = curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, &data_callback_dispatcher); + cRet = (*curl_easy_setopt_f)(c, CURLOPT_WRITEFUNCTION, &data_callback_dispatcher); if(cRet != CURLE_OK) - Fatal("Failed setting libcurl data callback function: %s", curl_easy_strerror(cRet)); - cRet = curl_easy_setopt(c, CURLOPT_WRITEDATA, this); + Fatal("Failed setting libcurl data callback function: %s", (*curl_easy_strerror_f)(cRet)); + cRet = (*curl_easy_setopt_f)(c, CURLOPT_WRITEDATA, this); if(cRet != CURLE_OK) - Fatal("Failed setting libcurl data callback object: %s", curl_easy_strerror(cRet)); + Fatal("Failed setting libcurl data callback object: %s", (*curl_easy_strerror_f)(cRet)); /* Progress callback */ - cRet = curl_easy_setopt(c, CURLOPT_NOPROGRESS, 0); + cRet = (*curl_easy_setopt_f)(c, CURLOPT_NOPROGRESS, 0); if(cRet != CURLE_OK) - Fatal("Failed enabling libcurl progress callback function: %s", curl_easy_strerror(cRet)); - cRet = curl_easy_setopt(c, CURLOPT_PROGRESSFUNCTION, &progress_callback_dispatcher); + Fatal("Failed enabling libcurl progress callback function: %s", (*curl_easy_strerror_f)(cRet)); + cRet = (*curl_easy_setopt_f)(c, CURLOPT_PROGRESSFUNCTION, &progress_callback_dispatcher); if(cRet != CURLE_OK) - Fatal("Failed setting libcurl progress callback function: %s", curl_easy_strerror(cRet)); - cRet = curl_easy_setopt(c, CURLOPT_PROGRESSDATA, this); + Fatal("Failed setting libcurl progress callback function: %s", (*curl_easy_strerror_f)(cRet)); + cRet = (*curl_easy_setopt_f)(c, CURLOPT_PROGRESSDATA, this); if(cRet != CURLE_OK) - Fatal("Failed setting libcurl progress callback object: %s", curl_easy_strerror(cRet)); + Fatal("Failed setting libcurl progress callback object: %s", (*curl_easy_strerror_f)(cRet)); /* Set username and password */ if(!mUser.empty()) { - cRet = curl_easy_setopt(c, CURLOPT_USERNAME, mUser.c_str()); + cRet = (*curl_easy_setopt_f)(c, CURLOPT_USERNAME, mUser.c_str()); if(cRet != CURLE_OK) - Error("Failed setting username: %s", curl_easy_strerror(cRet)); + Error("Failed setting username: %s", (*curl_easy_strerror_f)(cRet)); } if(!mPass.empty()) { - cRet = curl_easy_setopt(c, CURLOPT_PASSWORD, mPass.c_str()); + cRet = (*curl_easy_setopt_f)(c, CURLOPT_PASSWORD, mPass.c_str()); if(cRet != CURLE_OK) - Error("Failed setting password: %s", curl_easy_strerror(cRet)); + Error("Failed setting password: %s", (*curl_easy_strerror_f)(cRet)); } /* Authenication preference */ - cRet = curl_easy_setopt(c, CURLOPT_HTTPAUTH, CURLAUTH_ANY); + cRet = (*curl_easy_setopt_f)(c, CURLOPT_HTTPAUTH, CURLAUTH_ANY); if(cRet != CURLE_OK) Warning("Failed setting libcurl acceptable http authenication methods: %s", curl_easy_strerror(cRet)); @@ -437,14 +463,14 @@ void* cURLCamera::thread_func() { tRet = 0; while(!bTerminate) { /* Do the work */ - cRet = curl_easy_perform(c); + cRet = (*curl_easy_perform_f)(c); if(mode == MODE_SINGLE) { if(cRet != CURLE_OK) { break; } /* Attempt to get the size of the file */ - cRet = curl_easy_getinfo(c, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &dSize); + cRet = (*curl_easy_getinfo_f)(c, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &dSize); if(cRet != CURLE_OK) { break; } @@ -475,7 +501,7 @@ void* cURLCamera::thread_func() { break; } else if (cRet != CURLE_OK) { /* Some error */ - Error("cURL Request failed: %s",curl_easy_strerror(cRet)); + Error("cURL Request failed: %s",(*curl_easy_strerror_f)(cRet)); if(attempt < CURL_MAXRETRY) { Error("Retrying.. Attempt %d of %d",attempt,CURL_MAXRETRY); /* Do a reset */ @@ -491,7 +517,7 @@ void* cURLCamera::thread_func() { } /* Cleanup */ - curl_easy_cleanup(c); + (*curl_easy_cleanup)(c); c = NULL; return (void*)tRet; diff --git a/src/zm_curl_camera.h b/src/zm_curl_camera.h index 816937a65..39f2b4e05 100644 --- a/src/zm_curl_camera.h +++ b/src/zm_curl_camera.h @@ -97,6 +97,18 @@ size_t data_callback_dispatcher(void *buffer, size_t size, size_t nmemb, void *u int progress_callback_dispatcher(void *userdata, double dltotal, double dlnow, double ultotal, double ulnow); void* thread_func_dispatcher(void* object); +/* Func ptrs for libcurl functions */ +CURLcode (*curl_global_init_f)(long); +void (*curl_global_cleanup_f)(void); +const char* (*curl_easy_strerror_f)(CURLcode); +char* (*curl_version_f)(void); +CURL* (*curl_easy_init_f)(void); +CURLcode (*curl_easy_getinfo_f)(CURL* , CURLINFO, ...); +CURLcode (*curl_easy_perform_f)(CURL*); +CURLcode (*curl_easy_setopt_f)(CURL*, CURLoption, ...); +void (*curl_easy_cleanup_f)(CURL*); + + #endif // HAVE_LIBCURL #endif // ZM_CURL_CAMERA_H