Skip to content

Instantly share code, notes, and snippets.

@bagder
Last active August 23, 2019 21:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bagder/20e913e0d6f0010465c63342d297de2d to your computer and use it in GitHub Desktop.
Save bagder/20e913e0d6f0010465c63342d297de2d to your computer and use it in GitHub Desktop.
HTTP/3 callback post problem with ngtcp2 backend

Description

I have to two test setups, one that sends the entire POST body in one go, and another that sends 44 bytes, one byte at a time.

I just can't get test 2 to send me any h3 response at all from the cloudflare server.

Test branch

curl git master (as of 0a5d28fa2ec, merged Aug 23, 2019)

build with ngtcp2 draft-22 and nghttp3 from master (as of Aug 23, 2019 - no earlier)

Test case 1

This sends the 3 bytes in one go

./src/curl -d moo --http3 https://cloudflare-quic.com/b/post

Test case 2

Build the code below, link with libcurl, run it.

#include <stdio.h>
#include <string.h>
#include <curl/curl.h>

static const char data[]="this is what we post to the silly web server";

struct WriteThis {
  const char *readptr;
  long sizeleft;
};

static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp)
{
  struct WriteThis *pooh = (struct WriteThis *)userp;

  if(size*nmemb < 1)
    return 0;

  if(pooh->sizeleft) {
    *(char *)ptr = pooh->readptr[0]; /* copy one single byte */
    pooh->readptr++;                 /* advance pointer */
    pooh->sizeleft--;                /* less data left */
    return 1;                        /* we return 1 byte at a time! */
  }

  fprintf(stderr, "debugit says EOF\n");
  return 0;                          /* no more data left to deliver */
}

int main(void)
{
  CURL *curl;
  CURLcode res;

  struct WriteThis pooh;

  pooh.readptr = data;
  pooh.sizeleft = (long)strlen(data);

  /* In windows, this will init the winsock stuff */
  res = curl_global_init(CURL_GLOBAL_DEFAULT);
  /* Check for errors */
  if(res != CURLE_OK) {
    fprintf(stderr, "curl_global_init() failed: %s\n",
            curl_easy_strerror(res));
    return 1;
  }

  /* get a curl handle */
  curl = curl_easy_init();
  if(curl) {
    /* First set the URL that is about to receive our POST. */
    curl_easy_setopt(curl, CURLOPT_URL, "https://cloudflare-quic.com/b/post");

    /* Forcing HTTP/3 will make the connection fail if the server isn't
       accessible over QUIC + HTTP/3 on the given host and port.  Consider
       using CURLOPT_ALTSVC instead! */
    curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, (long)CURL_HTTP_VERSION_3);

    /* Now specify we want to POST data */
    curl_easy_setopt(curl, CURLOPT_POST, 1L);

    /* we want to use our own read function */
    curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);

    /* pointer to pass to our read function */
    curl_easy_setopt(curl, CURLOPT_READDATA, &pooh);

    /* get verbose debug output please */
    curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);

    /* Perform the request, res will get the return code */
    res = curl_easy_perform(curl);
    /* Check for errors */
    if(res != CURLE_OK)
      fprintf(stderr, "curl_easy_perform() failed: %s\n",
              curl_easy_strerror(res));

    /* always cleanup */
    curl_easy_cleanup(curl);
  }
  curl_global_cleanup();
  return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment