Skip to content

Instantly share code, notes, and snippets.

@lockie
Last active September 8, 2022 13:41
Show Gist options
  • Save lockie/3c8386c68fe24ca188589c48646505f2 to your computer and use it in GitHub Desktop.
Save lockie/3c8386c68fe24ca188589c48646505f2 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "curl/curl.h"
#define OUTPUTFILE "download"
#define URL "https://http2-server-push-demo.keksi.io"
static bool setup(CURL* hnd)
{
FILE* out = fopen(OUTPUTFILE, "wb");
if(!out)
return false;
// write to this file
curl_easy_setopt(hnd, CURLOPT_WRITEDATA, out);
// set URL
curl_easy_setopt(hnd, CURLOPT_URL, URL);
// be verbose
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1);
// enable HTTP/2
curl_easy_setopt(hnd, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
// wait for pipe connection to confirm
curl_easy_setopt(hnd, CURLOPT_PIPEWAIT, 1);
return true;
}
#define UNUSED __attribute__ ((unused))
// called when there's an incoming server push
static int server_push_callback(UNUSED CURL* parent,
UNUSED CURL* easy,
UNUSED size_t num_headers,
UNUSED struct curl_pushheaders* headers,
UNUSED void* userp)
{
puts("Got incoming HTTP/2 server push");
return CURL_PUSH_DENY;
}
#define TIMEOUT 1000
int main(void)
{
CURLM* multi_handle = curl_multi_init();
CURL* easy = curl_easy_init();
if(!setup(easy))
{
fprintf(stderr, "failed\n");
return EXIT_FAILURE;
}
curl_multi_add_handle(multi_handle, easy);
curl_multi_setopt(multi_handle, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX);
curl_multi_setopt(multi_handle, CURLMOPT_PUSHFUNCTION, server_push_callback);
int transfers = 1; // we start with one
do
{
int still_running; // keep number of running handles
CURLMcode mc = curl_multi_perform(multi_handle, &still_running);
int numfds;
if(still_running)
// wait for activity, timeout or "nothing"
mc = curl_multi_wait(multi_handle, NULL, 0, TIMEOUT, &numfds);
if(mc)
break;
struct CURLMsg* m;
do
{
int msgq = 0;
m = curl_multi_info_read(multi_handle, &msgq);
if(m && (m->msg == CURLMSG_DONE))
{
CURL* e = m->easy_handle;
transfers--;
curl_multi_remove_handle(multi_handle, e);
curl_easy_cleanup(e);
}
} while(m);
} while(transfers);
curl_multi_cleanup(multi_handle);
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment