Last active
January 23, 2024 07:05
-
-
Save basuke/59b0b92183846f0424a66f1b3d53cdc6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <curl/curl.h> | |
#include <stddef.h> | |
#include <unistd.h> | |
static const char* STATE_0 = "started"; | |
static const char* STATE_1 = "paused"; | |
static const char* STATE_2 = "resumed"; | |
static size_t writeFunction(char* ptr, size_t blockSize, size_t numberOfBlocks, void* userData) | |
{ | |
CURL* handle = static_cast<CURL*>(userData); | |
long receivedSize = (blockSize * numberOfBlocks); | |
// pause transfer when this function is called at the first time | |
const char* state; | |
curl_easy_getinfo(handle, CURLINFO_PRIVATE, &state); | |
if (state == STATE_0) { | |
curl_easy_setopt(handle, CURLOPT_PRIVATE, STATE_1); | |
printf("> %p: pause\n", handle); | |
return CURL_WRITEFUNC_PAUSE; | |
} | |
printf("> %p: data received (%ld)\n", handle, receivedSize); | |
return receivedSize; | |
} | |
int main() | |
{ | |
// initialize multi handle with multiplexing = ON | |
CURLM* multiHandle = curl_multi_init(); | |
curl_multi_setopt(multiHandle, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX); | |
// initialize 4 easy handles for getting file1~4.dat | |
const char* urls[4] = { | |
"https://localhost:8080/file1.dat", | |
"https://localhost:8080/file2.dat", | |
"https://localhost:8080/file3.dat", | |
"https://localhost:8080/file4.dat" | |
}; | |
CURL* handles[4]; | |
for (int i = 0; i < 4; i++) { | |
handles[i] = curl_easy_init(); | |
curl_easy_setopt(handles[i], CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS); | |
curl_easy_setopt(handles[i], CURLOPT_PIPEWAIT, 1L); | |
curl_easy_setopt(handles[i], CURLOPT_SSL_ENABLE_ALPN, 1L); | |
curl_easy_setopt(handles[i], CURLOPT_SSL_ENABLE_NPN, 0L); | |
curl_easy_setopt(handles[i], CURLOPT_HTTPGET, 1L); | |
curl_easy_setopt(handles[i], CURLOPT_SSL_VERIFYPEER, 0L); | |
curl_easy_setopt(handles[i], CURLOPT_SSL_VERIFYHOST, 0L); | |
curl_easy_setopt(handles[i], CURLOPT_WRITEFUNCTION, writeFunction); | |
curl_easy_setopt(handles[i], CURLOPT_WRITEDATA, (void*)handles[i]); | |
curl_easy_setopt(handles[i], CURLOPT_URL, urls[i]); | |
curl_easy_setopt(handles[i], CURLOPT_PRIVATE, STATE_0); | |
curl_multi_add_handle(multiHandle, handles[i]); | |
} | |
// transfer is started here, and will be paused when | |
// receiving header is completed and receiving body is started | |
int runningHandles = 0; | |
int seconds = 0; | |
printf("> --------------: start\n"); | |
do { | |
curl_multi_perform(multiHandle, &runningHandles); | |
sleep(1); | |
for (int i = 0; i < 4; i++) { | |
curl_easy_setopt(handles[i], CURLOPT_PRIVATE, STATE_1); | |
printf("> %p: resume\n", handles[i]); | |
curl_easy_pause(handles[i], CURLPAUSE_CONT); | |
} | |
} while (runningHandles > 0); | |
printf("> --------------: cleanup\n"); | |
for (int i = 0; i < 4; i++) | |
curl_easy_cleanup(handles[i]); | |
curl_multi_cleanup(multiHandle); | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <curl/curl.h> | |
#include <stddef.h> | |
#include <unistd.h> | |
static const char* STATE_0 = "started"; | |
static const char* STATE_1 = "paused"; | |
static const char* STATE_2 = "resumed"; | |
bool shouldResume { false }; | |
static size_t writeFunction(char* ptr, size_t blockSize, size_t numberOfBlocks, void* userData) | |
{ | |
CURL* handle = static_cast<CURL*>(userData); | |
long receivedSize = (blockSize * numberOfBlocks); | |
// pause transfer when this function is called at the first time | |
const char* state; | |
curl_easy_getinfo(handle, CURLINFO_PRIVATE, &state); | |
if (state == STATE_0) { | |
curl_easy_setopt(handle, CURLOPT_PRIVATE, STATE_1); | |
printf("> %p: pause\n", handle); | |
return CURL_WRITEFUNC_PAUSE; | |
} | |
printf("> %p: data received (%ld)\n", handle, receivedSize); | |
return receivedSize; | |
} | |
static int progressCallback(void* clientp, double, double, double, double) | |
{ | |
if (!shouldResume) | |
return 0; | |
// resume transfer from callback | |
CURL* handle = static_cast<CURL*>(clientp); | |
const char* state; | |
curl_easy_getinfo(handle, CURLINFO_PRIVATE, &state); | |
if (state == STATE_1) { | |
curl_easy_setopt(handle, CURLOPT_PRIVATE, STATE_2); | |
printf("> %p: resume\n", handle); | |
curl_easy_pause(handle, CURLPAUSE_CONT); | |
} | |
return 0; | |
} | |
int main() | |
{ | |
// initialize multi handle with multiplexing = ON | |
CURLM* multiHandle = curl_multi_init(); | |
curl_multi_setopt(multiHandle, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX); | |
// initialize 4 easy handles for getting file1~4.dat | |
const char* urls[4] = { | |
"https://localhost:8080/file1.dat", | |
"https://localhost:8080/file2.dat", | |
"https://localhost:8080/file3.dat", | |
"https://localhost:8080/file4.dat" | |
}; | |
CURL* handles[4]; | |
for (int i = 0; i < 4; i++) { | |
handles[i] = curl_easy_init(); | |
curl_easy_setopt(handles[i], CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS); | |
curl_easy_setopt(handles[i], CURLOPT_PIPEWAIT, 1L); | |
curl_easy_setopt(handles[i], CURLOPT_SSL_ENABLE_ALPN, 1L); | |
curl_easy_setopt(handles[i], CURLOPT_SSL_ENABLE_NPN, 0L); | |
curl_easy_setopt(handles[i], CURLOPT_HTTPGET, 1L); | |
curl_easy_setopt(handles[i], CURLOPT_SSL_VERIFYPEER, 0L); | |
curl_easy_setopt(handles[i], CURLOPT_SSL_VERIFYHOST, 0L); | |
curl_easy_setopt(handles[i], CURLOPT_WRITEFUNCTION, writeFunction); | |
curl_easy_setopt(handles[i], CURLOPT_WRITEDATA, (void*)handles[i]); | |
curl_easy_setopt(handles[i], CURLOPT_NOPROGRESS, 0L); | |
curl_easy_setopt(handles[i], CURLOPT_PROGRESSFUNCTION, progressCallback); | |
curl_easy_setopt(handles[i], CURLOPT_PROGRESSDATA, (void*)handles[i]); | |
curl_easy_setopt(handles[i], CURLOPT_URL, urls[i]); | |
curl_easy_setopt(handles[i], CURLOPT_PRIVATE, STATE_0); | |
curl_multi_add_handle(multiHandle, handles[i]); | |
} | |
// transfer is started here, and will be paused when | |
// receiving header is completed and receiving body is started | |
int runningHandles = 0; | |
int seconds = 0; | |
printf("> --------------: start\n"); | |
do { | |
curl_multi_perform(multiHandle, &runningHandles); | |
sleep(1); | |
seconds++; | |
// turn ON the resume flag 10 seconds after the start of transfer | |
if (seconds == 10) | |
shouldResume = true; | |
} while (runningHandles > 0); | |
printf("> --------------: cleanup\n"); | |
for (int i = 0; i < 4; i++) | |
curl_easy_cleanup(handles[i]); | |
curl_multi_cleanup(multiHandle); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment