mirror of
https://github.com/Aitum/obs-aitum-multistream.git
synced 2024-11-24 19:32:44 +01:00
162 lines
3.9 KiB
C
162 lines
3.9 KiB
C
#include "file-updater.h"
|
|
#include <curl/curl.h>
|
|
#include <obs-data.h>
|
|
#include <util/darray.h>
|
|
#include <util/dstr.h>
|
|
#include <util/platform.h>
|
|
#include <util/threading.h>
|
|
|
|
#if defined(_WIN32) && LIBCURL_VERSION_NUM >= 0x072c00
|
|
|
|
#ifdef CURLSSLOPT_REVOKE_BEST_EFFORT
|
|
#define CURL_OBS_REVOKE_SETTING CURLSSLOPT_REVOKE_BEST_EFFORT
|
|
#else
|
|
#define CURL_OBS_REVOKE_SETTING CURLSSLOPT_NO_REVOKE
|
|
#endif
|
|
|
|
#define curl_obs_set_revoke_setting(handle) curl_easy_setopt(handle, CURLOPT_SSL_OPTIONS, CURL_OBS_REVOKE_SETTING)
|
|
|
|
#else
|
|
|
|
#define curl_obs_set_revoke_setting(handle)
|
|
|
|
#endif
|
|
|
|
#define warn(msg, ...) blog(LOG_WARNING, "%s" msg, info->log_prefix, ##__VA_ARGS__)
|
|
#define info(msg, ...) blog(LOG_WARNING, "%s" msg, info->log_prefix, ##__VA_ARGS__)
|
|
|
|
struct update_info {
|
|
char error[CURL_ERROR_SIZE];
|
|
struct curl_slist *header;
|
|
DARRAY(uint8_t) file_data;
|
|
char *user_agent;
|
|
CURL *curl;
|
|
char *url;
|
|
|
|
confirm_file_callback_t callback;
|
|
void *param;
|
|
|
|
pthread_t thread;
|
|
bool thread_created;
|
|
char *log_prefix;
|
|
};
|
|
|
|
void update_info_destroy(struct update_info *info)
|
|
{
|
|
if (!info)
|
|
return;
|
|
|
|
if (info->thread_created)
|
|
pthread_join(info->thread, NULL);
|
|
|
|
da_free(info->file_data);
|
|
bfree(info->log_prefix);
|
|
bfree(info->user_agent);
|
|
bfree(info->url);
|
|
|
|
if (info->header)
|
|
curl_slist_free_all(info->header);
|
|
if (info->curl)
|
|
curl_easy_cleanup(info->curl);
|
|
bfree(info);
|
|
}
|
|
|
|
static size_t http_write(void *ptr, size_t size, size_t nmemb, void *uinfo)
|
|
{
|
|
size_t total = size * nmemb;
|
|
struct update_info *info = (struct update_info *)uinfo;
|
|
|
|
if (total)
|
|
da_push_back_array(info->file_data, ptr, total);
|
|
|
|
return total;
|
|
}
|
|
|
|
static bool do_http_request(struct update_info *info, const char *url, long *response_code)
|
|
{
|
|
CURLcode code;
|
|
uint8_t null_terminator = 0;
|
|
|
|
da_resize(info->file_data, 0);
|
|
curl_easy_setopt(info->curl, CURLOPT_URL, url);
|
|
curl_easy_setopt(info->curl, CURLOPT_HTTPHEADER, info->header);
|
|
curl_easy_setopt(info->curl, CURLOPT_ERRORBUFFER, info->error);
|
|
curl_easy_setopt(info->curl, CURLOPT_WRITEFUNCTION, http_write);
|
|
curl_easy_setopt(info->curl, CURLOPT_WRITEDATA, info);
|
|
curl_easy_setopt(info->curl, CURLOPT_FAILONERROR, true);
|
|
curl_easy_setopt(info->curl, CURLOPT_NOSIGNAL, 1);
|
|
curl_easy_setopt(info->curl, CURLOPT_ACCEPT_ENCODING, "");
|
|
curl_obs_set_revoke_setting(info->curl);
|
|
|
|
code = curl_easy_perform(info->curl);
|
|
if (code != CURLE_OK) {
|
|
warn("Remote update of URL \"%s\" failed: %s", url, info->error);
|
|
return false;
|
|
}
|
|
|
|
if (curl_easy_getinfo(info->curl, CURLINFO_RESPONSE_CODE, response_code) != CURLE_OK)
|
|
return false;
|
|
|
|
if (*response_code >= 400) {
|
|
warn("Remote update of URL \"%s\" failed: HTTP/%ld", url, *response_code);
|
|
return false;
|
|
}
|
|
|
|
da_push_back(info->file_data, &null_terminator);
|
|
|
|
return true;
|
|
}
|
|
|
|
struct file_update_data {
|
|
const char *name;
|
|
int version;
|
|
bool newer;
|
|
bool found;
|
|
};
|
|
|
|
static void *single_file_thread(void *data)
|
|
{
|
|
struct update_info *info = data;
|
|
struct file_download_data download_data;
|
|
long response_code;
|
|
|
|
info->curl = curl_easy_init();
|
|
if (!info->curl) {
|
|
warn("Could not initialize Curl");
|
|
return NULL;
|
|
}
|
|
|
|
if (!do_http_request(info, info->url, &response_code))
|
|
return NULL;
|
|
if (!info->file_data.array || !info->file_data.array[0])
|
|
return NULL;
|
|
|
|
download_data.name = info->url;
|
|
download_data.version = 0;
|
|
download_data.buffer.da = info->file_data.da;
|
|
info->callback(info->param, &download_data);
|
|
info->file_data.da = download_data.buffer.da;
|
|
return NULL;
|
|
}
|
|
|
|
update_info_t *update_info_create_single(const char *log_prefix, const char *user_agent, const char *file_url,
|
|
confirm_file_callback_t confirm_callback, void *param)
|
|
{
|
|
struct update_info *info;
|
|
|
|
if (!log_prefix)
|
|
log_prefix = "";
|
|
|
|
info = bzalloc(sizeof(*info));
|
|
info->log_prefix = bstrdup(log_prefix);
|
|
info->user_agent = bstrdup(user_agent);
|
|
info->url = bstrdup(file_url);
|
|
info->callback = confirm_callback;
|
|
info->param = param;
|
|
|
|
if (pthread_create(&info->thread, NULL, single_file_thread, info) == 0)
|
|
info->thread_created = true;
|
|
|
|
return info;
|
|
}
|