Switch to curl_multi

FossilOrigin-Name: 45caa8672395503ccfe940a18057ec3d3f182bd15f2f1ce5dda614e7ca89adfa
This commit is contained in:
nekobit 2022-07-19 03:56:57 +00:00
parent 570bf94ef5
commit 7373faab3f
7 changed files with 76 additions and 39 deletions

View file

@ -28,6 +28,7 @@ struct mstdnt_fetch_results
size_t mstdnt_curl_write_callback(char* ptr, size_t _size, size_t nmemb, void* _content);
void mastodont_fetch_results_cleanup(struct mstdnt_fetch_results* res);
int mastodont_fetch_curl(mastodont_t* mstdnt,
CURL* curl,
struct mstdnt_args* args,
char* url,
struct mstdnt_fetch_results* results,

View file

@ -35,7 +35,7 @@ typedef int8_t mstdnt_bool;
typedef struct mastodont
{
CURL* curl;
CURLM* curl;
} mastodont_t;
struct mstdnt_storage

View file

@ -29,13 +29,13 @@ typedef char* mstdnt_visibility_t;
enum mstdnt_visibility_type
{
MSTDNT_VISIBILITY_UNKNOWN,
MSTDNT_VISIBILITY_PUBLIC,
MSTDNT_VISIBILITY_UNLISTED,
MSTDNT_VISIBILITY_PRIVATE,
MSTDNT_VISIBILITY_LIST,
MSTDNT_VISIBILITY_DIRECT,
MSTDNT_VISIBILITY_LOCAL,
MSTDNT_VISIBILITY_LIST,
MSTDNT_VISIBILITY_UNKNOWN,
};
#endif /* MASTODONT_VISIBILITY_TYPES_H */

View file

@ -45,6 +45,7 @@ void mastodont_fetch_results_cleanup(struct mstdnt_fetch_results* res)
#define TOKEN_STR_SIZE 512
int mastodont_fetch_curl(mastodont_t* mstdnt,
CURL* curl,
struct mstdnt_args* m_args,
char* _url,
struct mstdnt_fetch_results* results,
@ -52,7 +53,10 @@ int mastodont_fetch_curl(mastodont_t* mstdnt,
char* request_t_custom)
{
#define is_custom request_t_custom && request_t == CURLOPT_CUSTOMREQUEST
int res = 3;
CURLMcode res = 3;
int status = 0;
CURLMsg* msg;
int running = 1;
char token[TOKEN_STR_SIZE] = { 0 };
struct curl_slist* list = NULL;
@ -67,35 +71,51 @@ int mastodont_fetch_curl(mastodont_t* mstdnt,
snprintf(token, TOKEN_STR_SIZE, "Authorization: Bearer %s",
m_args->token);
list = curl_slist_append(list, token);
curl_easy_setopt(mstdnt->curl, CURLOPT_HTTPHEADER, list);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
}
/* Set options */
curl_easy_setopt(mstdnt->curl, CURLOPT_URL, url);
curl_easy_setopt(mstdnt->curl, CURLOPT_WRITEFUNCTION, mstdnt_curl_write_callback);
curl_easy_setopt(mstdnt->curl, CURLOPT_WRITEDATA, results);
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, mstdnt_curl_write_callback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, results);
/* Should we verify the peer's SSL cert? */
curl_easy_setopt(mstdnt->curl, CURLOPT_SSL_VERIFYPEER,
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER,
!MSTDNT_T_FLAG_ISSET(m_args, MSTDNT_FLAG_SSL_UNVERIFIED));
curl_easy_setopt(mstdnt->curl, CURLOPT_SSL_VERIFYHOST,
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST,
!MSTDNT_T_FLAG_ISSET(m_args, MSTDNT_FLAG_SSL_UNVERIFIED));
/* PUT, POST, GET, Custom */
/* Mimes are expected to be set beforehand manually */
if (is_custom)
curl_easy_setopt(mstdnt->curl, request_t, request_t_custom);
curl_easy_setopt(curl, request_t, request_t_custom);
else if (request_t != CURLOPT_MIMEPOST)
curl_easy_setopt(mstdnt->curl, request_t, 1);
curl_easy_setopt(curl, request_t, 1);
res = curl_easy_perform(mstdnt->curl);
// Add curl handle to multi, then run and block
curl_multi_add_handle(mstdnt->curl, curl);
// Reset values that are optional
// Reset if custom
if (is_custom)
curl_easy_setopt(mstdnt->curl, request_t, NULL);
int msgs_left;
while (running)
{
res = curl_multi_perform(mstdnt->curl, &running);
curl_easy_setopt(mstdnt->curl, CURLOPT_HTTPHEADER, NULL);
if (running)
res = curl_multi_poll(mstdnt->curl, NULL, 0, 1000, NULL);
// Check if our socket is done
while ((msg = curl_multi_info_read(mstdnt->curl, &msgs_left)))
if (msg->msg == CURLMSG_DONE && msg->easy_handle == curl)
{
status = msg->data.result;
goto out;
}
if (res) break;
}
out:
// Looks like we're done here
curl_multi_remove_handle(mstdnt->curl, curl);
if (list) curl_slist_free_all(list);
return res;
return status;
}

View file

@ -13,15 +13,16 @@ void mastodont_global_curl_cleanup()
curl_global_cleanup();
}
// Curl multi can still be used with single context's
int mastodont_init(mastodont_t* data)
{
data->curl = curl_easy_init();
data->curl = curl_multi_init();
return data->curl == NULL;
}
void mastodont_cleanup(mastodont_t* data)
{
curl_easy_cleanup(data->curl);
curl_multi_cleanup(data->curl);
}
void mastodont_free(void* ptr)

View file

@ -85,6 +85,9 @@ int mastodont_request(mastodont_t* data,
_mstdnt_query_string(data, m_args, args->url, args->params_query, args->params_query_len) :
args->url;
// Create cURL single handle, we will run this later and then block
CURL* curl = curl_easy_init();
/* Zero out */
memset(storage, 0, sizeof(struct mstdnt_storage));
storage->needs_cleanup = 0;
@ -94,13 +97,13 @@ int mastodont_request(mastodont_t* data,
args->request_type == CURLOPT_CUSTOMREQUEST))
{
post = _mstdnt_query_string(data, m_args, NULL, args->params_post, args->params_post_len);
curl_easy_setopt(data->curl, CURLOPT_POSTFIELDS, post);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post);
}
else if (args->params_post && args->request_type == CURLOPT_MIMEPOST)
{
/* Initialize MIME post */
mime = curl_mime_init(data->curl);
curl_easy_setopt(data->curl, args->request_type, mime);
mime = curl_mime_init(curl);
curl_easy_setopt(curl, args->request_type, mime);
/* Let's handle query params array */
mime_params_post(mime, args->params_post, args->params_post_len);
@ -108,9 +111,10 @@ int mastodont_request(mastodont_t* data,
/* Make it empty, no post data provided */
/* I'm not sure why the pleroma api does this */
else if (args->request_type == CURLOPT_POST)
curl_easy_setopt(data->curl, CURLOPT_POSTFIELDS, "");
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "");
curlerror = mastodont_fetch_curl(data,
curl,
m_args,
url_query,
&results,
@ -136,7 +140,7 @@ int mastodont_request(mastodont_t* data,
// Make sure there is no error
if (!mstdnt_check_error(storage))
{
/* Optional */
/* Call our callback and do the large work */
if (args->callback) res = args->callback(storage->root, args->args);
}
else
@ -145,6 +149,9 @@ int mastodont_request(mastodont_t* data,
cleanup_res:
mastodont_fetch_results_cleanup(&results);
cleanup:
// Note: the fetch removed the handle from our multi handle
curl_easy_cleanup(curl);
if (args->params_post && args->request_type == CURLOPT_POST) free(post);
/* Only free if params_query set */
if (args->params_query) free(url_query);

View file

@ -20,22 +20,30 @@ int mastodont_instance_panel(mastodont_t* api,
struct mstdnt_args* m_args,
struct mstdnt_fetch_results* html)
{
return mastodont_fetch_curl(api,
m_args,
"instance/panel.html",
html,
CURLOPT_HTTPGET,
NULL);
CURL* curl = curl_easy_init();
int status = mastodont_fetch_curl(api,
curl,
m_args,
"instance/panel.html",
html,
CURLOPT_HTTPGET,
NULL);
curl_easy_cleanup(curl);
return status;
}
int mastodont_terms_of_service(mastodont_t* api,
struct mstdnt_args* m_args,
struct mstdnt_fetch_results* html)
{
return mastodont_fetch_curl(api,
m_args,
"static/terms-of-service.html",
html,
CURLOPT_HTTPGET,
NULL);
CURL* curl = curl_easy_init();
int status = mastodont_fetch_curl(api,
curl,
m_args,
"static/terms-of-service.html",
html,
CURLOPT_HTTPGET,
NULL);
curl_easy_cleanup(curl);
return status;
}