mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-12 09:06:55 -04:00
Add support for loading libcurl dynamically
This commit is contained in:
parent
e22cb847fe
commit
62ae7da667
120
src/Http.c
120
src/Http.c
@ -26,9 +26,6 @@
|
||||
#elif defined CC_BUILD_WEB
|
||||
/* Use fetch/XMLHttpRequest api for Emscripten */
|
||||
#include <emscripten/fetch.h>
|
||||
#elif defined CC_BUILD_CURL
|
||||
#include <curl/curl.h>
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
void HttpRequest_Free(struct HttpRequest* request) {
|
||||
@ -652,10 +649,75 @@ static void Http_SysFree(void) {
|
||||
InternetCloseHandle(hInternet);
|
||||
}
|
||||
#elif defined CC_BUILD_CURL
|
||||
#include "Errors.h"
|
||||
#include <stdint.h>
|
||||
typedef void CURL;
|
||||
struct curl_slist;
|
||||
typedef int CURLcode;
|
||||
|
||||
#define CURL_GLOBAL_DEFAULT ((1<<0) | (1<<1)) /* SSL and Win32 options */
|
||||
#define CURLOPT_WRITEDATA (10000 + 1)
|
||||
#define CURLOPT_URL (10000 + 2)
|
||||
#define CURLOPT_ERRORBUFFER (10000 + 10)
|
||||
#define CURLOPT_WRITEFUNCTION (20000 + 11)
|
||||
#define CURLOPT_POSTFIELDS (10000 + 15)
|
||||
#define CURLOPT_USERAGENT (10000 + 18)
|
||||
#define CURLOPT_HTTPHEADER (10000 + 23)
|
||||
#define CURLOPT_HEADERDATA (10000 + 29)
|
||||
#define CURLOPT_VERBOSE (0 + 41)
|
||||
#define CURLOPT_HEADER (0 + 42)
|
||||
#define CURLOPT_NOBODY (0 + 44)
|
||||
#define CURLOPT_POST (0 + 47)
|
||||
#define CURLOPT_FOLLOWLOCATION (0 + 52)
|
||||
#define CURLOPT_AUTOREFERER (0 + 58)
|
||||
#define CURLOPT_POSTFIELDSIZE (0 + 60)
|
||||
#define CURLOPT_MAXREDIRS (0 + 68)
|
||||
#define CURLOPT_HEADERFUNCTION (20000 + 79)
|
||||
|
||||
#if defined _WIN32
|
||||
#define APIENTRY __cdecl
|
||||
#else
|
||||
#define APIENTRY
|
||||
#endif
|
||||
|
||||
typedef CURLcode (APIENTRY *FP_curl_global_init)(long flags); static FP_curl_global_init _curl_global_init;
|
||||
typedef void (APIENTRY *FP_curl_global_cleanup)(void); static FP_curl_global_cleanup _curl_global_cleanup;
|
||||
typedef CURL* (APIENTRY *FP_curl_easy_init)(void); static FP_curl_easy_init _curl_easy_init;
|
||||
typedef CURLcode (APIENTRY *FP_curl_easy_perform)(CURL *c); static FP_curl_easy_perform _curl_easy_perform;
|
||||
typedef CURLcode (APIENTRY *FP_curl_easy_setopt)(CURL *c, int opt, ...); static FP_curl_easy_setopt _curl_easy_setopt;
|
||||
typedef void (APIENTRY *FP_curl_easy_reset)(CURL* c); static FP_curl_easy_reset _curl_easy_reset;
|
||||
typedef void (APIENTRY *FP_curl_easy_cleanup)(CURL* c); static FP_curl_easy_cleanup _curl_easy_cleanup;
|
||||
typedef const char* (APIENTRY *FP_curl_easy_strerror)(CURLcode res); static FP_curl_easy_strerror _curl_easy_strerror;
|
||||
typedef void (APIENTRY *FP_curl_slist_free_all)(struct curl_slist* l); static FP_curl_slist_free_all _curl_slist_free_all;
|
||||
typedef struct curl_slist* (APIENTRY *FP_curl_slist_append)(struct curl_slist* l, const char* v); static FP_curl_slist_append _curl_slist_append;
|
||||
|
||||
#if defined CC_BUILD_WIN
|
||||
static const String curlLib = String_FromConst("libcurl.dll");
|
||||
#elif defined CC_BUILD_OSX
|
||||
static const String curlLib = String_FromConst("libcurl.dylib");
|
||||
#else
|
||||
static const String curlLib = String_FromConst("libcurl.so.4");
|
||||
#endif
|
||||
|
||||
#define QUOTE(x) #x
|
||||
#define LoadCurlFunc(sym) (_ ## sym = (FP_ ## sym)DynamicLib_Get2(lib, QUOTE(sym)))
|
||||
static cc_bool LoadCurlFuncs(void) {
|
||||
void* lib = DynamicLib_Load2(&curlLib);
|
||||
if (!lib) { Logger_DynamicLibWarn("loading", &curlLib); return false; }
|
||||
|
||||
return
|
||||
LoadCurlFunc(curl_global_init) && LoadCurlFunc(curl_global_cleanup) &&
|
||||
LoadCurlFunc(curl_easy_init) && LoadCurlFunc(curl_easy_perform) &&
|
||||
LoadCurlFunc(curl_easy_setopt) && LoadCurlFunc(curl_easy_reset) &&
|
||||
LoadCurlFunc(curl_easy_cleanup) && LoadCurlFunc(curl_easy_strerror) &&
|
||||
LoadCurlFunc(curl_slist_free_all) && LoadCurlFunc(curl_slist_append);
|
||||
}
|
||||
|
||||
static CURL* curl;
|
||||
static cc_bool curlInited;
|
||||
|
||||
cc_bool Http_DescribeError(cc_result res, String* dst) {
|
||||
const char* err = curl_easy_strerror((CURLcode)res);
|
||||
const char* err = _curl_easy_strerror((CURLcode)res);
|
||||
if (!err) return false;
|
||||
|
||||
String_AppendConst(dst, err);
|
||||
@ -663,11 +725,13 @@ cc_bool Http_DescribeError(cc_result res, String* dst) {
|
||||
}
|
||||
|
||||
static void Http_SysInit(void) {
|
||||
CURLcode res = curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||
if (!LoadCurlFuncs()) return;
|
||||
CURLcode res = _curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||
if (res) Logger_Abort2(res, "Failed to init curl");
|
||||
|
||||
curl = curl_easy_init();
|
||||
curl = _curl_easy_init();
|
||||
if (!curl) Logger_Abort("Failed to init easy curl");
|
||||
curlInited = true;
|
||||
}
|
||||
|
||||
static struct curl_slist* headers_list;
|
||||
@ -677,7 +741,7 @@ static void Http_AddHeader(const char* key, const String* value) {
|
||||
String_Format2(&tmp, "%c: %s", key, value);
|
||||
|
||||
tmp.buffer[tmp.length] = '\0';
|
||||
headers_list = curl_slist_append(headers_list, tmp.buffer);
|
||||
headers_list = _curl_slist_append(headers_list, tmp.buffer);
|
||||
}
|
||||
|
||||
/* Processes a HTTP header downloaded from the server */
|
||||
@ -707,14 +771,14 @@ static size_t Http_ProcessData(char *buffer, size_t size, size_t nitems, void* u
|
||||
|
||||
/* Sets general curl options for a request */
|
||||
static void Http_SetCurlOpts(struct HttpRequest* req) {
|
||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, GAME_APP_NAME);
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 20L);
|
||||
_curl_easy_setopt(curl, CURLOPT_USERAGENT, GAME_APP_NAME);
|
||||
_curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
_curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 20L);
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, Http_ProcessHeader);
|
||||
curl_easy_setopt(curl, CURLOPT_HEADERDATA, req);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, Http_ProcessData);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, req);
|
||||
_curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, Http_ProcessHeader);
|
||||
_curl_easy_setopt(curl, CURLOPT_HEADERDATA, req);
|
||||
_curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, Http_ProcessData);
|
||||
_curl_easy_setopt(curl, CURLOPT_WRITEDATA, req);
|
||||
}
|
||||
|
||||
static cc_result Http_SysDo(struct HttpRequest* req, String* url) {
|
||||
@ -722,21 +786,26 @@ static cc_result Http_SysDo(struct HttpRequest* req, String* url) {
|
||||
void* post_data = req->data;
|
||||
CURLcode res;
|
||||
|
||||
curl_easy_reset(curl);
|
||||
if (!curlInited) {
|
||||
HttpRequest_Free(req);
|
||||
return ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
_curl_easy_reset(curl);
|
||||
headers_list = NULL;
|
||||
Http_SetRequestHeaders(req);
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers_list);
|
||||
_curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers_list);
|
||||
|
||||
Http_SetCurlOpts(req);
|
||||
Platform_ConvertString(urlStr, url);
|
||||
curl_easy_setopt(curl, CURLOPT_URL, urlStr);
|
||||
_curl_easy_setopt(curl, CURLOPT_URL, urlStr);
|
||||
|
||||
if (req->requestType == REQUEST_TYPE_HEAD) {
|
||||
curl_easy_setopt(curl, CURLOPT_NOBODY, 1L);
|
||||
_curl_easy_setopt(curl, CURLOPT_NOBODY, 1L);
|
||||
} else if (req->requestType == REQUEST_TYPE_POST) {
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, req->size);
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, req->data);
|
||||
_curl_easy_setopt(curl, CURLOPT_POST, 1L);
|
||||
_curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, req->size);
|
||||
_curl_easy_setopt(curl, CURLOPT_POSTFIELDS, req->data);
|
||||
|
||||
/* per curl docs, we must persist POST data until request finishes */
|
||||
req->data = NULL;
|
||||
@ -745,18 +814,19 @@ static cc_result Http_SysDo(struct HttpRequest* req, String* url) {
|
||||
|
||||
bufferSize = 0;
|
||||
http_curProgress = ASYNC_PROGRESS_FETCHING_DATA;
|
||||
res = curl_easy_perform(curl);
|
||||
res = _curl_easy_perform(curl);
|
||||
http_curProgress = 100;
|
||||
|
||||
curl_slist_free_all(headers_list);
|
||||
_curl_slist_free_all(headers_list);
|
||||
/* can free now that request has finished */
|
||||
Mem_Free(post_data);
|
||||
return res;
|
||||
}
|
||||
|
||||
static void Http_SysFree(void) {
|
||||
curl_easy_cleanup(curl);
|
||||
curl_global_cleanup();
|
||||
if (!curlInited) return;
|
||||
_curl_easy_cleanup(curl);
|
||||
_curl_global_cleanup();
|
||||
}
|
||||
#elif defined CC_BUILD_ANDROID
|
||||
struct HttpRequest* java_req;
|
||||
|
Loading…
x
Reference in New Issue
Block a user