2018-07-22 12:50:51 +02:00
|
|
|
#include "network.h"
|
|
|
|
|
2019-04-30 09:05:46 +02:00
|
|
|
#include "cache.h"
|
|
|
|
|
2018-07-24 18:37:23 +02:00
|
|
|
#include <openssl/crypto.h>
|
|
|
|
|
2018-07-21 01:39:51 +02:00
|
|
|
#include <errno.h>
|
2018-07-23 19:46:52 +02:00
|
|
|
#include <pthread.h>
|
2018-07-22 12:50:51 +02:00
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
2018-07-24 03:40:53 +02:00
|
|
|
#include <unistd.h>
|
2018-07-18 17:26:26 +02:00
|
|
|
|
2019-04-26 21:37:49 +02:00
|
|
|
#define DEFAULT_NETWORK_MAX_CONNS 10
|
|
|
|
#define DEFAULT_HTTP_429_WAIT 5
|
2019-04-19 00:10:07 +02:00
|
|
|
|
2018-07-30 15:20:04 +02:00
|
|
|
/* ----------------- External variables ---------------------- */
|
|
|
|
CURLSH *CURL_SHARE;
|
|
|
|
NetworkConfigStruct NETWORK_CONFIG;
|
2019-04-26 21:37:49 +02:00
|
|
|
int HTTP_429_WAIT = DEFAULT_HTTP_429_WAIT;
|
2018-07-24 04:16:47 +02:00
|
|
|
|
2018-07-25 01:51:05 +02:00
|
|
|
/* ----------------- Static variable ----------------------- */
|
2018-07-23 21:55:20 +02:00
|
|
|
/** \brief curl multi interface handle */
|
|
|
|
static CURLM *curl_multi;
|
2018-07-25 04:01:12 +02:00
|
|
|
/** \brief mutex for transfer functions */
|
2018-07-24 16:22:18 +02:00
|
|
|
static pthread_mutex_t transfer_lock;
|
2018-07-24 18:37:23 +02:00
|
|
|
/** \brief the lock array for cryptographic functions */
|
|
|
|
static pthread_mutex_t *crypto_lockarray;
|
2018-07-30 15:20:04 +02:00
|
|
|
/** \brief mutex for curl share interface itself */
|
2018-07-24 16:22:18 +02:00
|
|
|
static pthread_mutex_t curl_lock;
|
2018-07-30 15:20:04 +02:00
|
|
|
/** \brief network configuration */
|
2018-07-23 19:46:52 +02:00
|
|
|
|
2018-07-25 01:51:05 +02:00
|
|
|
/* -------------------- Functions -------------------------- */
|
2019-08-24 19:13:47 +02:00
|
|
|
#pragma GCC diagnostic push
|
|
|
|
#pragma GCC diagnostic ignored "-Wunused-function"
|
2019-08-27 11:52:46 +02:00
|
|
|
/**
|
2019-09-01 09:52:18 +02:00
|
|
|
* \brief OpenSSL 1.02 cryptography callback function
|
|
|
|
* \details Required for OpenSSL 1.02, but not OpenSSL 1.1
|
2019-08-27 11:52:46 +02:00
|
|
|
*/
|
2018-07-25 02:06:54 +02:00
|
|
|
static void crypto_lock_callback(int mode, int type, char *file, int line)
|
2018-07-25 01:51:05 +02:00
|
|
|
{
|
2018-07-25 02:06:54 +02:00
|
|
|
(void)file;
|
|
|
|
(void)line;
|
|
|
|
if(mode & CRYPTO_LOCK) {
|
2019-09-01 02:21:40 +02:00
|
|
|
PTHREAD_MUTEX_LOCK(&(crypto_lockarray[type]));
|
2018-07-25 02:06:54 +02:00
|
|
|
} else {
|
2019-09-01 02:21:40 +02:00
|
|
|
PTHREAD_MUTEX_UNLOCK(&(crypto_lockarray[type]));
|
2018-07-25 02:06:54 +02:00
|
|
|
}
|
|
|
|
}
|
2018-07-24 16:22:18 +02:00
|
|
|
|
2019-08-27 11:52:46 +02:00
|
|
|
/**
|
2019-09-01 09:52:18 +02:00
|
|
|
* \brief OpenSSL 1.02 thread ID function
|
|
|
|
* \details Required for OpenSSL 1.02, but not OpenSSL 1.1
|
2019-08-27 11:52:46 +02:00
|
|
|
*/
|
2019-04-22 14:32:15 +02:00
|
|
|
static unsigned long thread_id(void)
|
|
|
|
{
|
|
|
|
unsigned long ret;
|
|
|
|
|
|
|
|
ret = (unsigned long)pthread_self();
|
|
|
|
return ret;
|
|
|
|
}
|
2019-08-24 19:13:47 +02:00
|
|
|
#pragma GCC diagnostic pop
|
2019-04-22 14:32:15 +02:00
|
|
|
|
2018-07-25 02:06:54 +02:00
|
|
|
static void crypto_lock_init(void)
|
|
|
|
{
|
|
|
|
int i;
|
2018-07-24 16:22:18 +02:00
|
|
|
|
2018-07-25 02:06:54 +02:00
|
|
|
crypto_lockarray = (pthread_mutex_t *)OPENSSL_malloc(CRYPTO_num_locks() *
|
|
|
|
sizeof(pthread_mutex_t));
|
|
|
|
for(i = 0; i<CRYPTO_num_locks(); i++) {
|
|
|
|
pthread_mutex_init(&(crypto_lockarray[i]), NULL);
|
2018-07-24 03:40:53 +02:00
|
|
|
}
|
2018-07-25 02:06:54 +02:00
|
|
|
|
|
|
|
CRYPTO_set_id_callback((unsigned long (*)())thread_id);
|
|
|
|
CRYPTO_set_locking_callback((void (*)())crypto_lock_callback);
|
2018-07-23 21:55:20 +02:00
|
|
|
}
|
2018-07-23 19:46:52 +02:00
|
|
|
|
2018-07-24 03:40:53 +02:00
|
|
|
/**
|
2019-09-01 09:52:18 +02:00
|
|
|
* \brief Curl share handle callback function
|
|
|
|
* \details Adapted from:
|
2019-04-24 04:43:43 +02:00
|
|
|
* https://curl.haxx.se/libcurl/c/threaded-shared-conn.html
|
2018-07-24 03:40:53 +02:00
|
|
|
*/
|
2018-07-25 05:51:38 +02:00
|
|
|
static void curl_callback_lock(CURL *handle, curl_lock_data data,
|
2018-07-25 02:06:54 +02:00
|
|
|
curl_lock_access access, void *userptr)
|
|
|
|
{
|
|
|
|
(void)access; /* unused */
|
|
|
|
(void)userptr; /* unused */
|
|
|
|
(void)handle; /* unused */
|
|
|
|
(void)data; /* unused */
|
2019-09-01 02:21:40 +02:00
|
|
|
PTHREAD_MUTEX_LOCK(&curl_lock);
|
2018-07-25 02:06:54 +02:00
|
|
|
}
|
|
|
|
|
2018-07-25 05:51:38 +02:00
|
|
|
static void curl_callback_unlock(CURL *handle, curl_lock_data data,
|
2018-07-25 02:06:54 +02:00
|
|
|
void *userptr)
|
|
|
|
{
|
|
|
|
(void)userptr; /* unused */
|
|
|
|
(void)handle; /* unused */
|
|
|
|
(void)data; /* unused */
|
2019-09-01 02:21:40 +02:00
|
|
|
PTHREAD_MUTEX_UNLOCK(&curl_lock);
|
2018-07-25 02:06:54 +02:00
|
|
|
}
|
|
|
|
|
2019-04-24 04:43:43 +02:00
|
|
|
/**
|
2019-09-01 09:52:18 +02:00
|
|
|
* \brief Process a curl message
|
|
|
|
* \details Adapted from:
|
2019-04-24 04:43:43 +02:00
|
|
|
* https://curl.haxx.se/libcurl/c/10-at-a-time.html
|
|
|
|
*/
|
2019-04-27 05:40:26 +02:00
|
|
|
static void curl_process_msgs(CURLMsg *curl_msg, int n_running_curl,
|
|
|
|
int n_mesgs)
|
2019-04-22 14:32:15 +02:00
|
|
|
{
|
2019-04-22 16:26:25 +02:00
|
|
|
(void) n_running_curl;
|
|
|
|
(void) n_mesgs;
|
2019-04-26 17:20:01 +02:00
|
|
|
static int slept = 0;
|
2019-04-22 14:32:15 +02:00
|
|
|
if (curl_msg->msg == CURLMSG_DONE) {
|
|
|
|
TransferStruct *transfer;
|
|
|
|
CURL *curl = curl_msg->easy_handle;
|
|
|
|
curl_easy_getinfo(curl_msg->easy_handle, CURLINFO_PRIVATE,
|
|
|
|
&transfer);
|
|
|
|
transfer->transferring = 0;
|
|
|
|
char *url = NULL;
|
|
|
|
curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &url);
|
2019-04-26 15:14:42 +02:00
|
|
|
|
|
|
|
/* Wait for 5 seconds if we get HTTP 429 */
|
|
|
|
long http_resp = 0;
|
|
|
|
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_resp);
|
|
|
|
if (http_resp == HTTP_TOO_MANY_REQUESTS) {
|
2019-04-26 17:20:01 +02:00
|
|
|
if (!slept) {
|
2019-04-26 21:39:29 +02:00
|
|
|
fprintf(stderr,
|
|
|
|
"curl_process_msgs(): HTTP 429, sleeping for %d sec\n",
|
|
|
|
HTTP_429_WAIT);
|
2019-04-26 17:20:01 +02:00
|
|
|
sleep(HTTP_429_WAIT);
|
|
|
|
slept = 1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
slept = 0;
|
2019-04-26 15:14:42 +02:00
|
|
|
}
|
|
|
|
|
2019-04-27 02:53:09 +02:00
|
|
|
if (!curl_msg->data.result) {
|
2019-04-22 14:32:15 +02:00
|
|
|
/* Transfer successful, query the file size */
|
|
|
|
if (transfer->type == FILESTAT) {
|
|
|
|
Link_set_stat(transfer->link, curl);
|
|
|
|
}
|
2019-04-27 02:53:09 +02:00
|
|
|
} else {
|
|
|
|
fprintf(stderr, "curl_process_msgs(): %d - %s <%s>\n",
|
|
|
|
curl_msg->data.result,
|
|
|
|
curl_easy_strerror(curl_msg->data.result),
|
|
|
|
url);
|
2019-04-22 14:32:15 +02:00
|
|
|
}
|
|
|
|
curl_multi_remove_handle(curl_multi, curl);
|
|
|
|
/* clean up the handle, if we are querying the file size */
|
|
|
|
if (transfer->type == FILESTAT) {
|
|
|
|
curl_easy_cleanup(curl);
|
|
|
|
free(transfer);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
fprintf(stderr, "curl_process_msgs(): curl_msg->msg: %d\n",
|
|
|
|
curl_msg->msg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-27 02:53:09 +02:00
|
|
|
/**
|
2019-09-01 09:52:18 +02:00
|
|
|
* \details effectively based on
|
2019-04-27 02:53:09 +02:00
|
|
|
* https://curl.haxx.se/libcurl/c/multi-double.html
|
|
|
|
*/
|
2018-07-26 11:29:44 +02:00
|
|
|
int curl_multi_perform_once()
|
2018-07-24 03:40:53 +02:00
|
|
|
{
|
2019-08-31 22:21:28 +02:00
|
|
|
#ifdef NETWORK_LOCK_DEBUG
|
|
|
|
fprintf(stderr,
|
|
|
|
"curl_multi_perform_once(): thread %lu: locking transfer_lock;\n",
|
|
|
|
pthread_self());
|
|
|
|
#endif
|
2019-09-01 02:21:40 +02:00
|
|
|
PTHREAD_MUTEX_LOCK(&transfer_lock);
|
2018-07-24 03:40:53 +02:00
|
|
|
/* Get curl multi interface to perform pending tasks */
|
|
|
|
int n_running_curl;
|
2019-04-27 02:53:09 +02:00
|
|
|
CURLMcode mc = curl_multi_perform(curl_multi, &n_running_curl);
|
|
|
|
if(mc > 0) {
|
|
|
|
fprintf(stderr, "curl_multi_perform(): %s\n", curl_multi_strerror(mc));
|
2018-07-24 19:56:15 +02:00
|
|
|
}
|
|
|
|
|
2019-04-27 02:53:09 +02:00
|
|
|
fd_set fdread;
|
|
|
|
fd_set fdwrite;
|
|
|
|
fd_set fdexcep;
|
|
|
|
int maxfd = -1;
|
2018-07-24 19:56:15 +02:00
|
|
|
|
2019-04-27 02:53:09 +02:00
|
|
|
long curl_timeo = -1;
|
2018-07-24 03:40:53 +02:00
|
|
|
|
2019-04-27 02:53:09 +02:00
|
|
|
FD_ZERO(&fdread);
|
|
|
|
FD_ZERO(&fdwrite);
|
|
|
|
FD_ZERO(&fdexcep);
|
|
|
|
|
|
|
|
/* set a default timeout for select() */
|
|
|
|
struct timeval timeout;
|
|
|
|
timeout.tv_sec = 1;
|
|
|
|
timeout.tv_usec = 0;
|
|
|
|
|
|
|
|
curl_multi_timeout(curl_multi, &curl_timeo);
|
|
|
|
/* We effectively cap timeout to 1 sec */
|
|
|
|
if (curl_timeo >= 0) {
|
|
|
|
timeout.tv_sec = curl_timeo / 1000;
|
|
|
|
if (timeout.tv_sec > 1) {
|
|
|
|
timeout.tv_sec = 1;
|
|
|
|
} else {
|
|
|
|
timeout.tv_usec = (curl_timeo % 1000) * 1000;
|
2018-07-24 19:56:15 +02:00
|
|
|
}
|
2018-07-24 03:40:53 +02:00
|
|
|
}
|
|
|
|
|
2019-04-27 02:53:09 +02:00
|
|
|
/* get file descriptors from the transfers */
|
|
|
|
mc = curl_multi_fdset(curl_multi, &fdread, &fdwrite, &fdexcep, &maxfd);
|
2018-07-24 03:40:53 +02:00
|
|
|
|
2019-04-27 02:53:09 +02:00
|
|
|
if (mc > 0) {
|
|
|
|
fprintf(stderr, "curl_multi_fdset(): %s.\n", curl_multi_strerror(mc));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (maxfd == -1) {
|
|
|
|
usleep(100*1000);
|
|
|
|
} else {
|
|
|
|
if (select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout) < 0) {
|
|
|
|
fprintf(stderr, "curl_multi_perform_once(): select(): %s.\n",
|
|
|
|
strerror(errno));
|
|
|
|
}
|
2018-07-25 01:54:30 +02:00
|
|
|
}
|
2018-07-24 03:40:53 +02:00
|
|
|
|
2018-07-25 01:54:30 +02:00
|
|
|
/* Process the message queue */
|
|
|
|
int n_mesgs;
|
2018-07-24 03:40:53 +02:00
|
|
|
CURLMsg *curl_msg;
|
|
|
|
while((curl_msg = curl_multi_info_read(curl_multi, &n_mesgs))) {
|
2018-07-25 05:51:38 +02:00
|
|
|
curl_process_msgs(curl_msg, n_running_curl, n_mesgs);
|
|
|
|
}
|
2019-08-31 22:21:28 +02:00
|
|
|
#ifdef NETWORK_LOCK_DEBUG
|
|
|
|
fprintf(stderr,
|
|
|
|
"curl_multi_perform_once(): thread %lu: unlocking transfer_lock;\n",
|
|
|
|
pthread_self());
|
|
|
|
#endif
|
2019-09-01 02:21:40 +02:00
|
|
|
PTHREAD_MUTEX_UNLOCK(&transfer_lock);
|
2018-07-25 05:51:38 +02:00
|
|
|
return n_running_curl;
|
|
|
|
}
|
|
|
|
|
2018-07-30 15:20:04 +02:00
|
|
|
void network_config_init()
|
2018-07-25 01:51:05 +02:00
|
|
|
{
|
2018-07-30 15:20:04 +02:00
|
|
|
NETWORK_CONFIG.username = NULL;
|
|
|
|
NETWORK_CONFIG.password = NULL;
|
2018-07-30 15:55:38 +02:00
|
|
|
NETWORK_CONFIG.proxy = NULL;
|
|
|
|
NETWORK_CONFIG.proxy_user = NULL;
|
|
|
|
NETWORK_CONFIG.proxy_pass = NULL;
|
2019-04-26 12:27:39 +02:00
|
|
|
NETWORK_CONFIG.max_conns = DEFAULT_NETWORK_MAX_CONNS;
|
2019-04-26 12:39:03 +02:00
|
|
|
NETWORK_CONFIG.user_agent = "HTTPDirFS";
|
2019-04-30 09:05:46 +02:00
|
|
|
NETWORK_CONFIG.cache_enabled = 0;
|
|
|
|
NETWORK_CONFIG.cache_dir = NULL;
|
2018-07-30 15:20:04 +02:00
|
|
|
}
|
2018-07-25 01:51:05 +02:00
|
|
|
|
2018-07-30 15:20:04 +02:00
|
|
|
LinkTable *network_init(const char *url)
|
|
|
|
{
|
2018-07-25 04:01:12 +02:00
|
|
|
/* ------- Global related ----------*/
|
2018-07-25 01:51:05 +02:00
|
|
|
if (curl_global_init(CURL_GLOBAL_ALL)) {
|
|
|
|
fprintf(stderr, "network_init(): curl_global_init() failed!\n");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
2018-07-25 04:01:12 +02:00
|
|
|
/* -------- Share related ----------*/
|
2018-07-30 15:20:04 +02:00
|
|
|
CURL_SHARE = curl_share_init();
|
|
|
|
if (!(CURL_SHARE)) {
|
2018-07-25 01:51:05 +02:00
|
|
|
fprintf(stderr, "network_init(): curl_share_init() failed!\n");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
2019-07-21 09:41:02 +02:00
|
|
|
|
2018-07-30 15:20:04 +02:00
|
|
|
curl_share_setopt(CURL_SHARE, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE);
|
|
|
|
curl_share_setopt(CURL_SHARE, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS);
|
2019-07-21 09:41:02 +02:00
|
|
|
curl_share_setopt(CURL_SHARE, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION);
|
2018-07-25 01:51:05 +02:00
|
|
|
|
2018-07-25 01:54:30 +02:00
|
|
|
if (pthread_mutex_init(&curl_lock, NULL) != 0) {
|
2019-08-31 22:21:28 +02:00
|
|
|
fprintf(stderr, "network_init(): curl_lock initialisation failed!\n");
|
2018-07-25 01:51:05 +02:00
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
2018-07-30 15:20:04 +02:00
|
|
|
curl_share_setopt(CURL_SHARE, CURLSHOPT_LOCKFUNC, curl_callback_lock);
|
|
|
|
curl_share_setopt(CURL_SHARE, CURLSHOPT_UNLOCKFUNC, curl_callback_unlock);
|
2018-07-25 01:51:05 +02:00
|
|
|
|
2018-07-25 04:01:12 +02:00
|
|
|
/* ------------- Multi related -----------*/
|
2018-07-25 01:51:05 +02:00
|
|
|
curl_multi = curl_multi_init();
|
|
|
|
if (!curl_multi) {
|
|
|
|
fprintf(stderr, "network_init(): curl_multi_init() failed!\n");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
2019-04-09 00:05:27 +02:00
|
|
|
curl_multi_setopt(curl_multi, CURLMOPT_MAX_TOTAL_CONNECTIONS,
|
2018-07-30 15:20:04 +02:00
|
|
|
NETWORK_CONFIG.max_conns);
|
2019-04-28 02:24:35 +02:00
|
|
|
curl_multi_setopt(curl_multi, CURLMOPT_MAX_HOST_CONNECTIONS,
|
|
|
|
NETWORK_CONFIG.max_conns);
|
2018-07-25 01:51:05 +02:00
|
|
|
|
2018-07-25 04:01:12 +02:00
|
|
|
/* ------------ Initialise locks ---------*/
|
2019-04-23 20:37:01 +02:00
|
|
|
if (pthread_mutex_init(&transfer_lock, NULL)) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"network_init(): transfer_lock initialisation failed!\n");
|
2018-07-25 01:51:05 +02:00
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
2018-07-25 04:01:12 +02:00
|
|
|
/*
|
|
|
|
* cryptographic lock functions were shamelessly copied from
|
|
|
|
* https://curl.haxx.se/libcurl/c/threaded-ssl.html
|
|
|
|
*/
|
|
|
|
crypto_lock_init();
|
|
|
|
|
|
|
|
/* --------- Print off SSL engine version stream --------- */
|
2018-07-25 01:51:05 +02:00
|
|
|
curl_version_info_data *data = curl_version_info(CURLVERSION_NOW);
|
2019-04-22 16:26:25 +02:00
|
|
|
fprintf(stderr, "libcurl SSL engine: %s\n", data->ssl_version);
|
2018-07-25 01:51:05 +02:00
|
|
|
|
2019-04-22 14:32:15 +02:00
|
|
|
/* --------- Set the length of the root link ----------- */
|
2019-04-22 16:26:25 +02:00
|
|
|
/* This is where the '/' should be */
|
2019-04-26 08:39:45 +02:00
|
|
|
ROOT_LINK_OFFSET = strnlen(url, MAX_PATH_LEN) - 1;
|
2019-04-22 16:26:25 +02:00
|
|
|
if (url[ROOT_LINK_OFFSET] != '/') {
|
|
|
|
/*
|
|
|
|
* If '/' is not there, it is automatically added, so we need to skip 2
|
|
|
|
* characters
|
|
|
|
*/
|
|
|
|
ROOT_LINK_OFFSET += 2;
|
|
|
|
} else {
|
|
|
|
/* If '/' is there, we need to skip it */
|
|
|
|
ROOT_LINK_OFFSET += 1;
|
2019-04-22 14:32:15 +02:00
|
|
|
}
|
|
|
|
|
2019-04-30 09:05:46 +02:00
|
|
|
/* ----------- Enable cache system --------------------*/
|
|
|
|
if (NETWORK_CONFIG.cache_enabled) {
|
|
|
|
if (NETWORK_CONFIG.cache_dir) {
|
|
|
|
CacheSystem_init(NETWORK_CONFIG.cache_dir, 0);
|
|
|
|
} else {
|
|
|
|
CacheSystem_init(url, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-22 14:32:15 +02:00
|
|
|
/* ----------- Create the root link table --------------*/
|
2018-07-25 01:51:05 +02:00
|
|
|
ROOT_LINK_TBL = LinkTable_new(url);
|
2018-07-30 15:20:04 +02:00
|
|
|
return ROOT_LINK_TBL;
|
2018-07-25 01:51:05 +02:00
|
|
|
}
|
|
|
|
|
2018-07-26 11:29:44 +02:00
|
|
|
void transfer_blocking(CURL *curl)
|
2018-07-25 01:51:05 +02:00
|
|
|
{
|
2018-07-25 03:02:11 +02:00
|
|
|
/*
|
|
|
|
* We don't need to malloc here, as the transfer is finished before
|
|
|
|
* the variable gets popped from the stack
|
|
|
|
*/
|
2018-07-25 02:06:54 +02:00
|
|
|
volatile TransferStruct transfer;
|
|
|
|
transfer.type = DATA;
|
|
|
|
transfer.transferring = 1;
|
|
|
|
curl_easy_setopt(curl, CURLOPT_PRIVATE, &transfer);
|
2019-08-31 22:21:28 +02:00
|
|
|
#ifdef NETWORK_LOCK_DEBUG
|
|
|
|
fprintf(stderr,
|
|
|
|
"transfer_blocking(): thread %lu: locking transfer_lock;\n",
|
|
|
|
pthread_self());
|
|
|
|
#endif
|
2019-09-01 02:21:40 +02:00
|
|
|
PTHREAD_MUTEX_LOCK(&transfer_lock);
|
2018-07-25 01:51:05 +02:00
|
|
|
CURLMcode res = curl_multi_add_handle(curl_multi, curl);
|
2019-08-31 22:21:28 +02:00
|
|
|
#ifdef NETWORK_LOCK_DEBUG
|
|
|
|
fprintf(stderr,
|
|
|
|
"transfer_blocking(): thread %lu: unlocking transfer_lock;\n",
|
|
|
|
pthread_self());
|
|
|
|
#endif
|
2019-09-01 02:21:40 +02:00
|
|
|
PTHREAD_MUTEX_UNLOCK(&transfer_lock);
|
2018-07-25 01:51:05 +02:00
|
|
|
|
|
|
|
if(res > 0) {
|
2019-07-21 18:08:25 +02:00
|
|
|
fprintf(stderr, "transfer_blocking(): %d, %s\n",
|
2018-07-25 01:51:05 +02:00
|
|
|
res, curl_multi_strerror(res));
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
2018-07-25 02:06:54 +02:00
|
|
|
while (transfer.transferring) {
|
|
|
|
curl_multi_perform_once();
|
2018-07-25 01:51:05 +02:00
|
|
|
}
|
2018-07-25 02:06:54 +02:00
|
|
|
}
|
2018-07-25 01:51:05 +02:00
|
|
|
|
2018-07-26 11:29:44 +02:00
|
|
|
void transfer_nonblocking(CURL *curl)
|
2018-07-25 02:06:54 +02:00
|
|
|
{
|
2019-08-31 22:21:28 +02:00
|
|
|
#ifdef NETWORK_LOCK_DEBUG
|
|
|
|
fprintf(stderr,
|
|
|
|
"transfer_nonblocking(): thread %lu: locking transfer_lock;\n",
|
|
|
|
pthread_self());
|
|
|
|
#endif
|
2019-09-01 02:21:40 +02:00
|
|
|
PTHREAD_MUTEX_LOCK(&transfer_lock);
|
2018-07-25 02:06:54 +02:00
|
|
|
CURLMcode res = curl_multi_add_handle(curl_multi, curl);
|
2019-08-31 22:21:28 +02:00
|
|
|
#ifdef NETWORK_LOCK_DEBUG
|
|
|
|
fprintf(stderr,
|
|
|
|
"transfer_nonblocking(): thread %lu: unlocking transfer_lock;\n",
|
|
|
|
pthread_self());
|
|
|
|
#endif
|
2019-09-01 02:21:40 +02:00
|
|
|
PTHREAD_MUTEX_UNLOCK(&transfer_lock);
|
2019-08-31 09:10:36 +02:00
|
|
|
|
2018-07-25 02:06:54 +02:00
|
|
|
if(res > 0) {
|
2019-07-21 18:08:25 +02:00
|
|
|
fprintf(stderr, "transfer_nonblocking(): %s\n",
|
2019-04-27 02:53:09 +02:00
|
|
|
curl_multi_strerror(res));
|
2018-07-25 01:51:05 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-27 05:40:26 +02:00
|
|
|
size_t write_memory_callback(void *contents, size_t size, size_t nmemb,
|
|
|
|
void *userp)
|
2018-07-25 01:51:05 +02:00
|
|
|
{
|
|
|
|
size_t realsize = size * nmemb;
|
|
|
|
MemoryStruct *mem = (MemoryStruct *)userp;
|
2018-07-22 12:50:51 +02:00
|
|
|
|
2018-07-25 01:51:05 +02:00
|
|
|
mem->memory = realloc(mem->memory, mem->size + realsize + 1);
|
|
|
|
if(!mem->memory) {
|
|
|
|
/* out of memory! */
|
2018-07-30 15:20:04 +02:00
|
|
|
fprintf(stderr, "write_memory_callback(): realloc failure!\n");
|
2018-07-25 01:51:05 +02:00
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-04-27 05:40:26 +02:00
|
|
|
memmove(&mem->memory[mem->size], contents, realsize);
|
2018-07-25 01:51:05 +02:00
|
|
|
mem->size += realsize;
|
|
|
|
mem->memory[mem->size] = 0;
|
|
|
|
|
|
|
|
return realsize;
|
|
|
|
}
|