Path: blob/main/external/curl/tests/http/clients/h2-upgrade-extreme.c
2066 views
/***************************************************************************1* _ _ ____ _2* Project ___| | | | _ \| |3* / __| | | | |_) | |4* | (__| |_| | _ <| |___5* \___|\___/|_| \_\_____|6*7* Copyright (C) Daniel Stenberg, <[email protected]>, et al.8*9* This software is licensed as described in the file COPYING, which10* you should have received as part of this distribution. The terms11* are also available at https://curl.se/docs/copyright.html.12*13* You may opt to use, copy, modify, merge, publish, distribute and/or sell14* copies of the Software, and permit persons to whom the Software is15* furnished to do so, under the terms of the COPYING file.16*17* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY18* KIND, either express or implied.19*20* SPDX-License-Identifier: curl21*22***************************************************************************/23/* <DESC>24* HTTP/2 Upgrade test25* </DESC>26*/27#include <curl/curl.h>2829#include <stdio.h>30#include <stdlib.h>3132static void log_line_start(FILE *log, const char *idsbuf, curl_infotype type)33{34/*35* This is the trace look that is similar to what libcurl makes on its36* own.37*/38static const char * const s_infotype[] = {39"* ", "< ", "> ", "{ ", "} ", "{ ", "} "40};41if(idsbuf && *idsbuf)42fprintf(log, "%s%s", idsbuf, s_infotype[type]);43else44fputs(s_infotype[type], log);45}4647#define TRC_IDS_FORMAT_IDS_1 "[%" CURL_FORMAT_CURL_OFF_T "-x] "48#define TRC_IDS_FORMAT_IDS_2 "[%" CURL_FORMAT_CURL_OFF_T "-%" \49CURL_FORMAT_CURL_OFF_T "] "50/*51** callback for CURLOPT_DEBUGFUNCTION52*/53static int debug_cb(CURL *handle, curl_infotype type,54char *data, size_t size,55void *userdata)56{57FILE *output = stderr;58static int newl = 0;59static int traced_data = 0;60char idsbuf[60];61curl_off_t xfer_id, conn_id;6263(void)handle; /* not used */64(void)userdata;6566if(!curl_easy_getinfo(handle, CURLINFO_XFER_ID, &xfer_id) && xfer_id >= 0) {67if(!curl_easy_getinfo(handle, CURLINFO_CONN_ID, &conn_id) &&68conn_id >= 0) {69curl_msnprintf(idsbuf, sizeof(idsbuf), TRC_IDS_FORMAT_IDS_2, xfer_id,70conn_id);71}72else {73curl_msnprintf(idsbuf, sizeof(idsbuf), TRC_IDS_FORMAT_IDS_1, xfer_id);74}75}76else77idsbuf[0] = 0;7879switch(type) {80case CURLINFO_HEADER_OUT:81if(size > 0) {82size_t st = 0;83size_t i;84for(i = 0; i < size - 1; i++) {85if(data[i] == '\n') { /* LF */86if(!newl) {87log_line_start(output, idsbuf, type);88}89(void)fwrite(data + st, i - st + 1, 1, output);90st = i + 1;91newl = 0;92}93}94if(!newl)95log_line_start(output, idsbuf, type);96(void)fwrite(data + st, i - st + 1, 1, output);97}98newl = (size && (data[size - 1] != '\n')) ? 1 : 0;99traced_data = 0;100break;101case CURLINFO_TEXT:102case CURLINFO_HEADER_IN:103if(!newl)104log_line_start(output, idsbuf, type);105(void)fwrite(data, size, 1, output);106newl = (size && (data[size - 1] != '\n')) ? 1 : 0;107traced_data = 0;108break;109case CURLINFO_DATA_OUT:110case CURLINFO_DATA_IN:111case CURLINFO_SSL_DATA_IN:112case CURLINFO_SSL_DATA_OUT:113if(!traced_data) {114if(!newl)115log_line_start(output, idsbuf, type);116fprintf(output, "[%ld bytes data]\n", (long)size);117newl = 0;118traced_data = 1;119}120break;121default: /* nada */122newl = 0;123traced_data = 1;124break;125}126127return 0;128}129130static size_t write_cb(char *ptr, size_t size, size_t nmemb, void *opaque)131{132(void)ptr;133(void)opaque;134return size * nmemb;135}136137int main(int argc, char *argv[])138{139const char *url;140CURLM *multi = NULL;141CURL *easy;142CURLMcode mc;143int running_handles = 0, start_count, numfds;144CURLMsg *msg;145int msgs_in_queue;146char range[128];147int exitcode = 1;148149if(argc != 2) {150fprintf(stderr, "%s URL\n", argv[0]);151return 2;152}153154url = argv[1];155multi = curl_multi_init();156if(!multi) {157fprintf(stderr, "curl_multi_init failed\n");158goto cleanup;159}160161start_count = 200;162do {163if(start_count) {164easy = curl_easy_init();165if(!easy) {166fprintf(stderr, "curl_easy_init failed\n");167goto cleanup;168}169curl_easy_setopt(easy, CURLOPT_VERBOSE, 1L);170curl_easy_setopt(easy, CURLOPT_DEBUGFUNCTION, debug_cb);171curl_easy_setopt(easy, CURLOPT_URL, url);172curl_easy_setopt(easy, CURLOPT_NOSIGNAL, 1L);173curl_easy_setopt(easy, CURLOPT_AUTOREFERER, 1L);174curl_easy_setopt(easy, CURLOPT_FAILONERROR, 1L);175curl_easy_setopt(easy, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);176curl_easy_setopt(easy, CURLOPT_WRITEFUNCTION, write_cb);177curl_easy_setopt(easy, CURLOPT_WRITEDATA, NULL);178curl_easy_setopt(easy, CURLOPT_HTTPGET, 1L);179curl_msnprintf(range, sizeof(range),180"%" CURL_FORMAT_CURL_OFF_TU "-"181"%" CURL_FORMAT_CURL_OFF_TU,182(curl_off_t)0,183(curl_off_t)16384);184curl_easy_setopt(easy, CURLOPT_RANGE, range);185186mc = curl_multi_add_handle(multi, easy);187if(mc != CURLM_OK) {188fprintf(stderr, "curl_multi_add_handle: %s\n",189curl_multi_strerror(mc));190curl_easy_cleanup(easy);191goto cleanup;192}193--start_count;194}195196mc = curl_multi_perform(multi, &running_handles);197if(mc != CURLM_OK) {198fprintf(stderr, "curl_multi_perform: %s\n",199curl_multi_strerror(mc));200goto cleanup;201}202203if(running_handles) {204mc = curl_multi_poll(multi, NULL, 0, 1000000, &numfds);205if(mc != CURLM_OK) {206fprintf(stderr, "curl_multi_poll: %s\n",207curl_multi_strerror(mc));208goto cleanup;209}210}211212/* Check for finished handles and remove. */213/* !checksrc! disable EQUALSNULL 1 */214while((msg = curl_multi_info_read(multi, &msgs_in_queue)) != NULL) {215if(msg->msg == CURLMSG_DONE) {216long status = 0;217curl_off_t xfer_id;218curl_easy_getinfo(msg->easy_handle, CURLINFO_XFER_ID, &xfer_id);219curl_easy_getinfo(msg->easy_handle, CURLINFO_RESPONSE_CODE, &status);220if(msg->data.result == CURLE_SEND_ERROR ||221msg->data.result == CURLE_RECV_ERROR) {222/* We get these if the server had a GOAWAY in transit on223* re-using a connection */224}225else if(msg->data.result) {226fprintf(stderr, "transfer #%" CURL_FORMAT_CURL_OFF_T227": failed with %d\n", xfer_id, msg->data.result);228goto cleanup;229}230else if(status != 206) {231fprintf(stderr, "transfer #%" CURL_FORMAT_CURL_OFF_T232": wrong http status %ld (expected 206)\n", xfer_id, status);233goto cleanup;234}235curl_multi_remove_handle(multi, msg->easy_handle);236curl_easy_cleanup(msg->easy_handle);237fprintf(stderr, "transfer #%" CURL_FORMAT_CURL_OFF_T" retiring "238"(%d now running)\n", xfer_id, running_handles);239}240}241242fprintf(stderr, "running_handles=%d, yet_to_start=%d\n",243running_handles, start_count);244245} while(running_handles > 0 || start_count);246247fprintf(stderr, "exiting\n");248exitcode = EXIT_SUCCESS;249250cleanup:251252if(multi) {253CURL **list = curl_multi_get_handles(multi);254if(list) {255int i;256for(i = 0; list[i]; i++) {257curl_multi_remove_handle(multi, list[i]);258curl_easy_cleanup(list[i]);259}260curl_free(list);261}262curl_multi_cleanup(multi);263}264265return exitcode;266}267268269