Path: blob/main/external/curl/tests/http/clients/tls-session-reuse.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* TLS session reuse25* </DESC>26*/27#include <curl/curl.h>2829#include <stdio.h>30#include <stdlib.h>31#include <string.h>3233static void log_line_start(FILE *log, const char *idsbuf, curl_infotype type)34{35/*36* This is the trace look that is similar to what libcurl makes on its37* own.38*/39static const char * const s_infotype[] = {40"* ", "< ", "> ", "{ ", "} ", "{ ", "} "41};42if(idsbuf && *idsbuf)43fprintf(log, "%s%s", idsbuf, s_infotype[type]);44else45fputs(s_infotype[type], log);46}4748#define TRC_IDS_FORMAT_IDS_1 "[%" CURL_FORMAT_CURL_OFF_T "-x] "49#define TRC_IDS_FORMAT_IDS_2 "[%" CURL_FORMAT_CURL_OFF_T "-%" \50CURL_FORMAT_CURL_OFF_T "] "51/*52** callback for CURLOPT_DEBUGFUNCTION53*/54static int debug_cb(CURL *handle, curl_infotype type,55char *data, size_t size,56void *userdata)57{58FILE *output = stderr;59static int newl = 0;60static int traced_data = 0;61char idsbuf[60];62curl_off_t xfer_id, conn_id;6364(void)handle; /* not used */65(void)userdata;6667if(!curl_easy_getinfo(handle, CURLINFO_XFER_ID, &xfer_id) && xfer_id >= 0) {68if(!curl_easy_getinfo(handle, CURLINFO_CONN_ID, &conn_id) &&69conn_id >= 0) {70curl_msnprintf(idsbuf, sizeof(idsbuf), TRC_IDS_FORMAT_IDS_2, xfer_id,71conn_id);72}73else {74curl_msnprintf(idsbuf, sizeof(idsbuf), TRC_IDS_FORMAT_IDS_1, xfer_id);75}76}77else78idsbuf[0] = 0;7980switch(type) {81case CURLINFO_HEADER_OUT:82if(size > 0) {83size_t st = 0;84size_t i;85for(i = 0; i < size - 1; i++) {86if(data[i] == '\n') { /* LF */87if(!newl) {88log_line_start(output, idsbuf, type);89}90(void)fwrite(data + st, i - st + 1, 1, output);91st = i + 1;92newl = 0;93}94}95if(!newl)96log_line_start(output, idsbuf, type);97(void)fwrite(data + st, i - st + 1, 1, output);98}99newl = (size && (data[size - 1] != '\n')) ? 1 : 0;100traced_data = 0;101break;102case CURLINFO_TEXT:103case CURLINFO_HEADER_IN:104if(!newl)105log_line_start(output, idsbuf, type);106(void)fwrite(data, size, 1, output);107newl = (size && (data[size - 1] != '\n')) ? 1 : 0;108traced_data = 0;109break;110case CURLINFO_DATA_OUT:111case CURLINFO_DATA_IN:112case CURLINFO_SSL_DATA_IN:113case CURLINFO_SSL_DATA_OUT:114if(!traced_data) {115if(!newl)116log_line_start(output, idsbuf, type);117fprintf(output, "[%ld bytes data]\n", (long)size);118newl = 0;119traced_data = 1;120}121break;122default: /* nada */123newl = 0;124traced_data = 1;125break;126}127128return 0;129}130131static size_t write_cb(char *ptr, size_t size, size_t nmemb, void *opaque)132{133(void)ptr;134(void)opaque;135return size * nmemb;136}137138static int add_transfer(CURLM *multi, CURLSH *share,139struct curl_slist *resolve,140const char *url, long http_version)141{142CURL *easy;143CURLMcode mc;144145easy = curl_easy_init();146if(!easy) {147fprintf(stderr, "curl_easy_init failed\n");148return 1;149}150curl_easy_setopt(easy, CURLOPT_VERBOSE, 1L);151curl_easy_setopt(easy, CURLOPT_DEBUGFUNCTION, debug_cb);152curl_easy_setopt(easy, CURLOPT_URL, url);153curl_easy_setopt(easy, CURLOPT_SHARE, share);154curl_easy_setopt(easy, CURLOPT_NOSIGNAL, 1L);155curl_easy_setopt(easy, CURLOPT_AUTOREFERER, 1L);156curl_easy_setopt(easy, CURLOPT_FAILONERROR, 1L);157curl_easy_setopt(easy, CURLOPT_HTTP_VERSION, http_version);158curl_easy_setopt(easy, CURLOPT_WRITEFUNCTION, write_cb);159curl_easy_setopt(easy, CURLOPT_WRITEDATA, NULL);160curl_easy_setopt(easy, CURLOPT_HTTPGET, 1L);161curl_easy_setopt(easy, CURLOPT_SSL_VERIFYPEER, 0L);162if(resolve)163curl_easy_setopt(easy, CURLOPT_RESOLVE, resolve);164165166mc = curl_multi_add_handle(multi, easy);167if(mc != CURLM_OK) {168fprintf(stderr, "curl_multi_add_handle: %s\n",169curl_multi_strerror(mc));170curl_easy_cleanup(easy);171return 1;172}173return 0;174}175176int main(int argc, char *argv[])177{178const char *url;179CURLM *multi = NULL;180CURLMcode mc;181int running_handles = 0, numfds;182CURLMsg *msg;183CURLSH *share = NULL;184CURLU *cu;185struct curl_slist *resolve = NULL;186char resolve_buf[1024];187int msgs_in_queue;188int add_more, waits, ongoing = 0;189char *host = NULL, *port = NULL;190int http_version = CURL_HTTP_VERSION_1_1;191int exitcode = 1;192193if(argc != 3) {194fprintf(stderr, "%s proto URL\n", argv[0]);195return 2;196}197198if(!strcmp("h2", argv[1]))199http_version = CURL_HTTP_VERSION_2;200else if(!strcmp("h3", argv[1]))201http_version = CURL_HTTP_VERSION_3ONLY;202203url = argv[2];204cu = curl_url();205if(!cu) {206fprintf(stderr, "out of memory\n");207return 1;208}209if(curl_url_set(cu, CURLUPART_URL, url, 0)) {210fprintf(stderr, "not a URL: '%s'\n", url);211goto cleanup;212}213if(curl_url_get(cu, CURLUPART_HOST, &host, 0)) {214fprintf(stderr, "could not get host of '%s'\n", url);215goto cleanup;216}217if(curl_url_get(cu, CURLUPART_PORT, &port, 0)) {218fprintf(stderr, "could not get port of '%s'\n", url);219goto cleanup;220}221222curl_msnprintf(resolve_buf, sizeof(resolve_buf)-1, "%s:%s:127.0.0.1",223host, port);224resolve = curl_slist_append(resolve, resolve_buf);225226multi = curl_multi_init();227if(!multi) {228fprintf(stderr, "curl_multi_init failed\n");229goto cleanup;230}231232share = curl_share_init();233if(!share) {234fprintf(stderr, "curl_share_init failed\n");235goto cleanup;236}237curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION);238239240if(add_transfer(multi, share, resolve, url, http_version))241goto cleanup;242++ongoing;243add_more = 6;244waits = 3;245do {246mc = curl_multi_perform(multi, &running_handles);247if(mc != CURLM_OK) {248fprintf(stderr, "curl_multi_perform: %s\n",249curl_multi_strerror(mc));250goto cleanup;251}252253if(running_handles) {254mc = curl_multi_poll(multi, NULL, 0, 1000000, &numfds);255if(mc != CURLM_OK) {256fprintf(stderr, "curl_multi_poll: %s\n",257curl_multi_strerror(mc));258goto cleanup;259}260}261262if(waits) {263--waits;264}265else {266while(add_more) {267if(add_transfer(multi, share, resolve, url, http_version))268goto cleanup;269++ongoing;270--add_more;271}272}273274/* Check for finished handles and remove. */275/* !checksrc! disable EQUALSNULL 1 */276while((msg = curl_multi_info_read(multi, &msgs_in_queue)) != NULL) {277if(msg->msg == CURLMSG_DONE) {278long status = 0;279curl_off_t xfer_id;280curl_easy_getinfo(msg->easy_handle, CURLINFO_XFER_ID, &xfer_id);281curl_easy_getinfo(msg->easy_handle, CURLINFO_RESPONSE_CODE, &status);282if(msg->data.result == CURLE_SEND_ERROR ||283msg->data.result == CURLE_RECV_ERROR) {284/* We get these if the server had a GOAWAY in transit on285* re-using a connection */286}287else if(msg->data.result) {288fprintf(stderr, "transfer #%" CURL_FORMAT_CURL_OFF_T289": failed with %d\n", xfer_id, msg->data.result);290goto cleanup;291}292else if(status != 200) {293fprintf(stderr, "transfer #%" CURL_FORMAT_CURL_OFF_T294": wrong http status %ld (expected 200)\n", xfer_id, status);295goto cleanup;296}297curl_multi_remove_handle(multi, msg->easy_handle);298curl_easy_cleanup(msg->easy_handle);299--ongoing;300fprintf(stderr, "transfer #%" CURL_FORMAT_CURL_OFF_T" retiring "301"(%d now running)\n", xfer_id, running_handles);302}303}304305fprintf(stderr, "running_handles=%d, yet_to_start=%d\n",306running_handles, add_more);307308} while(ongoing || add_more);309310fprintf(stderr, "exiting\n");311exitcode = EXIT_SUCCESS;312313cleanup:314315if(multi) {316CURL **list = curl_multi_get_handles(multi);317if(list) {318int i;319for(i = 0; list[i]; i++) {320curl_multi_remove_handle(multi, list[i]);321curl_easy_cleanup(list[i]);322}323curl_free(list);324}325curl_multi_cleanup(multi);326}327curl_share_cleanup(share);328curl_slist_free_all(resolve);329curl_free(host);330curl_free(port);331curl_url_cleanup(cu);332333return exitcode;334}335336337