132 lines
3.3 KiB
C
132 lines
3.3 KiB
C
/*
|
|
|
|
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.
|
|
|
|
© 2021 dogeystamp <dogeystamp@disroot.org>
|
|
*/
|
|
|
|
#include <curl/curl.h>
|
|
#include <curl/easy.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "net.h"
|
|
#include "util.h"
|
|
#include "config.h"
|
|
|
|
static CURLM *multiHandle;
|
|
|
|
int
|
|
initCurl()
|
|
{
|
|
// Initialise the curl handle.
|
|
|
|
curl_global_init(CURL_GLOBAL_ALL);
|
|
multiHandle = curl_multi_init();
|
|
|
|
return !multiHandle;
|
|
}
|
|
|
|
static size_t
|
|
writeCallback(void *ptr, size_t size, size_t nmemb, void *data)
|
|
{
|
|
// Write blocks of data to the output.
|
|
|
|
size_t realsize = size * nmemb;
|
|
|
|
outputStruct *mem = (outputStruct*) data;
|
|
|
|
mem->buffer = realloc(mem->buffer, mem->size + realsize + 1);
|
|
|
|
if (mem->buffer) {
|
|
memcpy(&(mem->buffer[mem->size]), ptr, realsize);
|
|
|
|
mem->size += realsize;
|
|
mem->buffer[mem->size] = 0;
|
|
}
|
|
|
|
return realsize;
|
|
}
|
|
|
|
int
|
|
createRequest(const char* url, outputStruct *output)
|
|
{
|
|
// Create the curl request for an URL.
|
|
|
|
CURL *requestHandle = curl_easy_init();
|
|
|
|
if (!requestHandle)
|
|
logMsg(LOG_FATAL, "Can't initialise curl.\n");
|
|
|
|
output->buffer = NULL;
|
|
output->size = 0;
|
|
|
|
CURLcode stat;
|
|
if (curl_easy_setopt(requestHandle, CURLOPT_URL, url)) {
|
|
logMsg(LOG_ERROR, "Invalid URL: %s\n", url);
|
|
}
|
|
|
|
stat = curl_easy_setopt(requestHandle, CURLOPT_WRITEFUNCTION, writeCallback);
|
|
stat = curl_easy_setopt(requestHandle, CURLOPT_WRITEDATA, (void*)output);
|
|
stat = curl_easy_setopt(requestHandle, CURLOPT_MAXREDIRS, maxRedirs);
|
|
stat = curl_easy_setopt(requestHandle, CURLOPT_PROTOCOLS_STR, curlProtocols);
|
|
stat = curl_easy_setopt(requestHandle, CURLOPT_FOLLOWLOCATION, 1L);
|
|
|
|
if (stat) {
|
|
fprintf(stderr, "Unexpected curl error: %s.\n", curl_easy_strerror(stat));
|
|
return 1;
|
|
}
|
|
|
|
CURLMcode multiStat = curl_multi_add_handle(multiHandle, requestHandle);
|
|
if (multiStat) {
|
|
fprintf(stderr, "Unexpected curl error: %s.\n", curl_multi_strerror(multiStat));
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
performRequests(void callback(char *, long))
|
|
{
|
|
// Perform all the curl requests.
|
|
|
|
int runningRequests;
|
|
|
|
do {
|
|
curl_multi_wait(multiHandle, NULL, 0, 1000, NULL);
|
|
curl_multi_perform(multiHandle, &runningRequests);
|
|
|
|
CURLMsg* msg;
|
|
|
|
int queueMsgs;
|
|
|
|
while ((msg = curl_multi_info_read(multiHandle, &queueMsgs))) {
|
|
if (msg->msg == CURLMSG_DONE) {
|
|
CURL *requestHandle = msg->easy_handle;
|
|
|
|
char *url = NULL;
|
|
long responseCode = 0;
|
|
|
|
curl_easy_getinfo(requestHandle, CURLINFO_EFFECTIVE_URL, &url);
|
|
curl_easy_getinfo(requestHandle, CURLINFO_RESPONSE_CODE, &responseCode);
|
|
|
|
callback(url, responseCode);
|
|
|
|
curl_multi_remove_handle(multiHandle, requestHandle);
|
|
curl_easy_cleanup(requestHandle);
|
|
}
|
|
}
|
|
|
|
// > 0 because curl puts negative numbers when there's broken requests
|
|
} while (runningRequests > 0);
|
|
|
|
curl_multi_cleanup(multiHandle);
|
|
|
|
return 0;
|
|
}
|