mirror of
https://github.com/wiiu-env/libcurlwrapper.git
synced 2024-11-27 07:04:17 +01:00
274 lines
12 KiB
C++
274 lines
12 KiB
C++
#include "logger.h"
|
|
#include "macro_magic.h"
|
|
#include <cerrno>
|
|
#include <coreinit/debug.h>
|
|
#include <coreinit/dynload.h>
|
|
#include <cstdarg>
|
|
#include <forward_list>
|
|
#include <string_view>
|
|
#include <sys/socket.h>
|
|
|
|
static void *(*s_setsockopt)() = nullptr;
|
|
|
|
static bool sInitDone = false;
|
|
static OSDynLoad_Module sModuleHandle = nullptr;
|
|
static uint8_t *s_cacert_pem = nullptr;
|
|
static uint32_t *s_cacert_pem_size = nullptr;
|
|
|
|
std::forward_list<uint32_t *> functionHandles;
|
|
|
|
extern "C" int curl_global_init() {
|
|
if (sInitDone) {
|
|
return 0;
|
|
}
|
|
|
|
if (OSDynLoad_Acquire("homebrew_curlwrapper", &sModuleHandle) != OS_DYNLOAD_OK) {
|
|
DEBUG_FUNCTION_LINE_ERR("OSDynLoad_Acquire failed.");
|
|
return -1;
|
|
}
|
|
|
|
if (OSDynLoad_FindExport(sModuleHandle, OS_DYNLOAD_EXPORT_FUNC, "setsockopt", (void **) &s_setsockopt) != OS_DYNLOAD_OK) {
|
|
DEBUG_FUNCTION_LINE_ERR("FindExport setsockopt failed.");
|
|
return -2;
|
|
}
|
|
|
|
if (OSDynLoad_FindExport(sModuleHandle, OS_DYNLOAD_EXPORT_DATA, "cacert_pem", (void **) &s_cacert_pem) != OS_DYNLOAD_OK) {
|
|
DEBUG_FUNCTION_LINE_WARN("FindExport cacert_pem failed.");
|
|
}
|
|
|
|
if (OSDynLoad_FindExport(sModuleHandle, OS_DYNLOAD_EXPORT_DATA, "cacert_pem_size", (void **) &s_cacert_pem_size) != OS_DYNLOAD_OK) {
|
|
DEBUG_FUNCTION_LINE_WARN("FindExport cacert_pem_size failed.");
|
|
}
|
|
|
|
char *(*s_curl_version_tmp)() = nullptr;
|
|
if (OSDynLoad_FindExport(sModuleHandle, OS_DYNLOAD_EXPORT_FUNC, "curl_version", (void **) &s_curl_version_tmp) == OS_DYNLOAD_OK) {
|
|
const char *expectedCURLVersion1 = "libcurl/7.84.0";
|
|
const char *expectedCURLVersion2 = "libcurl/8.0.1";
|
|
if (!std::string_view(s_curl_version_tmp()).starts_with(expectedCURLVersion1) && !std::string_view(s_curl_version_tmp()).starts_with(expectedCURLVersion2)) {
|
|
DEBUG_FUNCTION_LINE_WARN("Unexpected libcurl version: %s (expected %s)", s_curl_version_tmp(), expectedCURLVersion2);
|
|
}
|
|
} else {
|
|
DEBUG_FUNCTION_LINE_WARN("Failed to check curl_version");
|
|
}
|
|
|
|
sInitDone = true;
|
|
return 0;
|
|
}
|
|
|
|
extern "C" void curl_global_cleanup() {
|
|
if (!sInitDone) { return; }
|
|
OSDynLoad_Release(sModuleHandle);
|
|
sModuleHandle = nullptr;
|
|
sInitDone = false;
|
|
s_setsockopt = nullptr;
|
|
s_cacert_pem = nullptr;
|
|
s_cacert_pem_size = nullptr;
|
|
for (auto &handle : functionHandles) {
|
|
*handle = 0;
|
|
}
|
|
functionHandles.clear();
|
|
}
|
|
|
|
extern "C" int curlwrapper_setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen) {
|
|
if (s_setsockopt == nullptr) {
|
|
if (curl_global_init() != 0 || s_setsockopt == nullptr) {
|
|
return ENOTSUP;
|
|
}
|
|
}
|
|
return reinterpret_cast<decltype(&setsockopt)>(s_setsockopt)(sockfd, level, optname, optval, optlen);
|
|
}
|
|
|
|
// Variadic function in curl header, but always has 3 args
|
|
static void *(*s_curl_easy_setopt)() = nullptr;
|
|
extern "C" int curl_easy_setopt(void *param1, void *param2, void *param3) {
|
|
if (s_curl_easy_setopt == nullptr) {
|
|
if (sModuleHandle == nullptr || OSDynLoad_FindExport(sModuleHandle, OS_DYNLOAD_EXPORT_FUNC, "curl_easy_setopt", (void **) &s_curl_easy_setopt) != OS_DYNLOAD_OK) {
|
|
DEBUG_FUNCTION_LINE_ERR("Failed to find export curl_easy_setopt");
|
|
return CURLE_FAILED_INIT;
|
|
} else {
|
|
functionHandles.push_front((uint32_t *) &s_curl_easy_setopt);
|
|
}
|
|
}
|
|
if ((uint32_t) param2 == 10000 + 149) { // CURLOPT_SOCKOPTDATA
|
|
if (s_setsockopt != nullptr && (uint32_t) param3 == 0x13371337) {
|
|
param3 = (void *) s_setsockopt;
|
|
}
|
|
}
|
|
|
|
return reinterpret_cast<decltype(&curl_easy_setopt)>(s_curl_easy_setopt)(param1, param2, param3);
|
|
}
|
|
|
|
// Variadic function in curl header, but always has 3 args
|
|
static void *(*s_curl_easy_init)() = nullptr;
|
|
extern "C" void *curl_easy_init() {
|
|
if (s_curl_easy_init == nullptr) {
|
|
if (sModuleHandle == nullptr || OSDynLoad_FindExport(sModuleHandle, OS_DYNLOAD_EXPORT_FUNC, "curl_easy_init", (void **) &s_curl_easy_init) != OS_DYNLOAD_OK) {
|
|
DEBUG_FUNCTION_LINE_ERR("Failed to find export curl_easy_init");
|
|
return nullptr;
|
|
} else {
|
|
functionHandles.push_front((uint32_t *) &s_curl_easy_init);
|
|
}
|
|
}
|
|
|
|
auto result = reinterpret_cast<decltype(&curl_easy_init)>(s_curl_easy_init)();
|
|
if (result != nullptr && s_cacert_pem != nullptr && s_cacert_pem_size != nullptr) {
|
|
struct curl_blob blob {};
|
|
blob.data = (void *) s_cacert_pem;
|
|
blob.len = *s_cacert_pem_size;
|
|
blob.flags = 1; /*CURL_BLOB_COPY*/
|
|
|
|
// Use the certificate bundle in the data
|
|
if (curl_easy_setopt(result, reinterpret_cast<void *>(40000 + 309) /*CURLOPT_CAINFO_BLOB*/, &blob) != 0) {
|
|
DEBUG_FUNCTION_LINE_WARN("Failed to set ca_certs");
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
MAGIC_FUNCTION(int, curl_easy_perform, CURLE_FAILED_INIT, arg1);
|
|
MAGIC_FUNCTION(void, curl_easy_cleanup, RETURN_VOID, arg1);
|
|
MAGIC_FUNCTION(int, curl_easy_getinfo, CURLE_FAILED_INIT, arg1, arg2, arg3);
|
|
MAGIC_FUNCTION(void *, curl_easy_duphandle, nullptr, arg1);
|
|
MAGIC_FUNCTION(void, curl_easy_reset, RETURN_VOID, arg1);
|
|
|
|
MAGIC_FUNCTION(int, curl_easy_recv, CURLE_FAILED_INIT, arg1, arg2, arg3, arg4);
|
|
MAGIC_FUNCTION(int, curl_easy_send, CURLE_FAILED_INIT, arg1, arg2, arg3, arg4);
|
|
MAGIC_FUNCTION(int, curl_easy_upkeep, CURLE_FAILED_INIT, arg1);
|
|
|
|
MAGIC_FUNCTION(int, curl_easy_header, CURLHE_NOT_BUILT_IN, arg1, arg2, arg3, arg4, arg5, arg6);
|
|
MAGIC_FUNCTION(void *, curl_easy_nextheader, nullptr, arg1, arg2, arg3, arg4);
|
|
|
|
MAGIC_FUNCTION(void *, curl_easy_option_by_name, nullptr, arg1);
|
|
MAGIC_FUNCTION(void *, curl_easy_option_by_id, nullptr, arg1);
|
|
MAGIC_FUNCTION(void *, curl_easy_option_next, nullptr, arg1);
|
|
|
|
MAGIC_FUNCTION_ARG0(void *, curl_url, nullptr);
|
|
MAGIC_FUNCTION(void, curl_url_cleanup, RETURN_VOID, arg1);
|
|
MAGIC_FUNCTION(void *, curl_url_dup, nullptr, arg1);
|
|
|
|
MAGIC_FUNCTION(int, curl_url_get, CURLUE_BAD_HANDLE, arg1, arg2, arg3, arg4);
|
|
MAGIC_FUNCTION(int, curl_url_set, CURLUE_BAD_HANDLE, arg1, arg2, arg3, arg4);
|
|
MAGIC_FUNCTION(const char *, curl_url_strerror, "[ERROR]", arg1);
|
|
|
|
MAGIC_FUNCTION(int, curl_strequal, 0, arg1, arg2);
|
|
MAGIC_FUNCTION(int, curl_strnequal, 0, arg1, arg2, arg3);
|
|
|
|
MAGIC_FUNCTION(void *, curl_mime_init, nullptr, arg1);
|
|
MAGIC_FUNCTION(void, curl_mime_free, RETURN_VOID, arg1);
|
|
MAGIC_FUNCTION(void *, curl_mime_addpart, nullptr, arg1);
|
|
MAGIC_FUNCTION(int, curl_mime_name, CURLE_FAILED_INIT, arg1, arg2);
|
|
MAGIC_FUNCTION(int, curl_mime_filename, CURLE_FAILED_INIT, arg1, arg2);
|
|
MAGIC_FUNCTION(int, curl_mime_type, CURLE_FAILED_INIT, arg1, arg2);
|
|
MAGIC_FUNCTION(int, curl_mime_encoder, CURLE_FAILED_INIT, arg1, arg2);
|
|
MAGIC_FUNCTION(int, curl_mime_data, CURLE_FAILED_INIT, arg1, arg2, arg3);
|
|
MAGIC_FUNCTION(int, curl_mime_filedata, CURLE_FAILED_INIT, arg1, arg2);
|
|
MAGIC_FUNCTION(int, curl_mime_data_cb, CURLE_FAILED_INIT, arg1, arg2, arg3, arg4, arg5, arg6);
|
|
MAGIC_FUNCTION(int, curl_mime_subparts, CURLE_FAILED_INIT, arg1, arg2);
|
|
MAGIC_FUNCTION(int, curl_mime_headers, CURLE_FAILED_INIT, arg1, arg2, arg3);
|
|
|
|
MAGIC_FUNCTION(int, curl_formadd, CURLE_FAILED_INIT, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
|
|
MAGIC_FUNCTION(int, curl_formget, CURLE_FAILED_INIT, arg1, arg2, arg3);
|
|
MAGIC_FUNCTION(void, curl_formfree, RETURN_VOID, arg1);
|
|
MAGIC_FUNCTION(char *, curl_getenv, nullptr, arg1);
|
|
MAGIC_FUNCTION_ARG0(const char *, curl_version, "[ERROR]");
|
|
MAGIC_FUNCTION(char *, curl_easy_escape, nullptr, arg1, arg2, arg3);
|
|
MAGIC_FUNCTION(char *, curl_escape, nullptr, arg1, arg2);
|
|
MAGIC_FUNCTION(char *, curl_easy_unescape, nullptr, arg1, arg2, arg3, arg4);
|
|
MAGIC_FUNCTION(char *, curl_unescape, nullptr, arg1, arg2);
|
|
MAGIC_FUNCTION(void, curl_free, RETURN_VOID, arg1);
|
|
MAGIC_FUNCTION(int, curl_global_init_mem, CURLE_FAILED_INIT, arg1, arg2, arg3, arg4, arg5, arg6);
|
|
|
|
MAGIC_FUNCTION(int, curl_global_sslset, CURLSSLSET_NO_BACKENDS, arg1, arg2, arg3);
|
|
MAGIC_FUNCTION(void *, curl_slist_append, nullptr, arg1, arg2);
|
|
MAGIC_FUNCTION(void, curl_slist_free_all, RETURN_VOID, arg1);
|
|
MAGIC_FUNCTION(time_t, curl_getdate, 0, arg1, arg2);
|
|
|
|
MAGIC_FUNCTION_ARG0(void *, curl_share_init, nullptr);
|
|
// Variadic function in curl header, but always has 3 args
|
|
MAGIC_FUNCTION(int, curl_share_setopt, CURLSHE_NOT_BUILT_IN, arg1, arg2, arg3);
|
|
MAGIC_FUNCTION(int, curl_share_cleanup, CURLSHE_NOT_BUILT_IN, arg1);
|
|
|
|
MAGIC_FUNCTION(void *, curl_version_info, nullptr, arg1);
|
|
|
|
MAGIC_FUNCTION(const char *, curl_easy_strerror, "[ERROR]", arg1);
|
|
MAGIC_FUNCTION(const char *, curl_share_strerror, "[ERROR]", arg1);
|
|
MAGIC_FUNCTION(int, curl_easy_pause, CURLE_FAILED_INIT, arg1, arg2);
|
|
|
|
MAGIC_FUNCTION_ARG0(void *, curl_multi_init, nullptr);
|
|
MAGIC_FUNCTION(int, curl_multi_add_handle, CURLM_INTERNAL_ERROR, arg1, arg2);
|
|
MAGIC_FUNCTION(int, curl_multi_remove_handle, CURLM_INTERNAL_ERROR, arg1, arg2);
|
|
MAGIC_FUNCTION(int, curl_multi_fdset, CURLM_INTERNAL_ERROR, arg1, arg2, arg3, arg4, arg5);
|
|
MAGIC_FUNCTION(int, curl_multi_wait, CURLM_INTERNAL_ERROR, arg1, arg2, arg3, arg4, arg5);
|
|
MAGIC_FUNCTION(int, curl_multi_poll, CURLM_INTERNAL_ERROR, arg1, arg2, arg3, arg4, arg5);
|
|
MAGIC_FUNCTION(int, curl_multi_wakeup, CURLM_INTERNAL_ERROR, arg1);
|
|
MAGIC_FUNCTION(int, curl_multi_perform, CURLM_INTERNAL_ERROR, arg1, arg2);
|
|
MAGIC_FUNCTION(int, curl_multi_cleanup, CURLM_INTERNAL_ERROR, arg1);
|
|
MAGIC_FUNCTION(void *, curl_multi_info_read, nullptr, arg1, arg2);
|
|
MAGIC_FUNCTION(const char *, curl_multi_strerror, "[ERROR]", arg1);
|
|
|
|
MAGIC_FUNCTION(int, curl_multi_socket, CURLM_INTERNAL_ERROR, arg1, arg2, arg3);
|
|
MAGIC_FUNCTION(int, curl_multi_socket_action, CURLM_INTERNAL_ERROR, arg1, arg2, arg3, arg4);
|
|
MAGIC_FUNCTION(int, curl_multi_socket_all, CURLM_INTERNAL_ERROR, arg1, arg2);
|
|
MAGIC_FUNCTION(int, curl_multi_timeout, CURLM_INTERNAL_ERROR, arg1, arg2);
|
|
// Variadic function in curl header, but always has 3 args
|
|
MAGIC_FUNCTION(int, curl_multi_setopt, CURLM_INTERNAL_ERROR, arg1, arg2, arg3);
|
|
MAGIC_FUNCTION(int, curl_multi_assign, CURLM_INTERNAL_ERROR, arg1, arg2, arg3);
|
|
MAGIC_FUNCTION(char *, curl_pushheader_bynum, nullptr, arg1, arg2);
|
|
MAGIC_FUNCTION(char *, curl_pushheader_byname, nullptr, arg1, arg2);
|
|
MAGIC_FUNCTION(int, curl_mvprintf, 0, arg1, arg2);
|
|
MAGIC_FUNCTION(int, curl_mvfprintf, 0, arg1, arg2, arg3);
|
|
MAGIC_FUNCTION(int, curl_mvsprintf, 0, arg1, arg2, arg3);
|
|
MAGIC_FUNCTION(int, curl_mvsnprintf, 0, arg1, arg2, arg3, arg4);
|
|
MAGIC_FUNCTION(char *, curl_mvaprintf, nullptr, arg1, arg2);
|
|
|
|
MAGIC_FUNCTION(int, curl_ws_recv, CURLM_INTERNAL_ERROR, arg1, arg2, arg3, arg4, arg5);
|
|
MAGIC_FUNCTION(int, curl_ws_send, CURLM_INTERNAL_ERROR, arg1, arg2, arg3, arg4, arg5);
|
|
|
|
extern "C" int curl_mprintf(const char *format, ...) {
|
|
va_list va;
|
|
|
|
va_start(va, format);
|
|
auto res = curl_mvprintf((void *) format, (void *) va);
|
|
va_end(va);
|
|
|
|
return res;
|
|
}
|
|
extern "C" int curl_mfprintf(FILE *fd, const char *format, ...) {
|
|
va_list va;
|
|
|
|
va_start(va, format);
|
|
auto res = curl_mvfprintf((void *) fd, (void *) format, (void *) va);
|
|
va_end(va);
|
|
|
|
return res;
|
|
}
|
|
extern "C" int curl_msprintf(char *buffer, const char *format, ...) {
|
|
va_list va;
|
|
|
|
va_start(va, format);
|
|
auto res = curl_mvsprintf((void *) buffer, (void *) format, (void *) va);
|
|
va_end(va);
|
|
|
|
return res;
|
|
}
|
|
|
|
extern "C" int curl_msnprintf(char *buffer, size_t maxlength, const char *format, ...) {
|
|
va_list va;
|
|
|
|
va_start(va, format);
|
|
auto res = curl_mvsnprintf((void *) buffer, (void *) maxlength, (void *) format, (void *) va);
|
|
va_end(va);
|
|
|
|
return res;
|
|
}
|
|
|
|
extern "C" char *curl_maprintf(const char *format, ...) {
|
|
va_list va;
|
|
|
|
va_start(va, format);
|
|
auto res = curl_mvaprintf((void *) format, (void *) va);
|
|
va_end(va);
|
|
|
|
return res;
|
|
}
|