Path: blob/main/external/curl/tests/libtest/cli_tls_session_reuse.c
2649 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#include "first.h"2425#include "testtrace.h"26#include "memdebug.h"2728static int tse_found_tls_session = FALSE;2930static size_t write_tse_cb(char *ptr, size_t size, size_t nmemb, void *opaque)31{32CURL *curl = opaque;33(void)ptr;34if(!tse_found_tls_session) {35struct curl_tlssessioninfo *tlssession;36CURLcode rc;3738rc = curl_easy_getinfo(curl, CURLINFO_TLS_SSL_PTR, &tlssession);39if(rc) {40curl_mfprintf(stderr, "curl_easy_getinfo(CURLINFO_TLS_SSL_PTR) "41"failed: %s\n", curl_easy_strerror(rc));42return rc;43}44if(tlssession->backend == CURLSSLBACKEND_NONE) {45curl_mfprintf(stderr, "curl_easy_getinfo(CURLINFO_TLS_SSL_PTR) "46"gave no backend\n");47return CURLE_FAILED_INIT;48}49if(!tlssession->internals) {50curl_mfprintf(stderr, "curl_easy_getinfo(CURLINFO_TLS_SSL_PTR) "51"missing\n");52return CURLE_FAILED_INIT;53}54tse_found_tls_session = TRUE;55}56return size * nmemb;57}5859static CURL *tse_add_transfer(CURLM *multi, CURLSH *share,60struct curl_slist *resolve,61const char *url, long http_version)62{63CURL *curl;64CURLMcode mc;6566curl = curl_easy_init();67if(!curl) {68curl_mfprintf(stderr, "curl_easy_init failed\n");69return NULL;70}71curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);72curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, cli_debug_cb);73curl_easy_setopt(curl, CURLOPT_URL, url);74curl_easy_setopt(curl, CURLOPT_SHARE, share);75curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);76curl_easy_setopt(curl, CURLOPT_AUTOREFERER, 1L);77curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);78curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, http_version);79curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_tse_cb);80curl_easy_setopt(curl, CURLOPT_WRITEDATA, curl);81curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L);82curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);83if(resolve)84curl_easy_setopt(curl, CURLOPT_RESOLVE, resolve);858687mc = curl_multi_add_handle(multi, curl);88if(mc != CURLM_OK) {89curl_mfprintf(stderr, "curl_multi_add_handle: %s\n",90curl_multi_strerror(mc));91curl_easy_cleanup(curl);92return NULL;93}94return curl;95}9697static CURLcode test_cli_tls_session_reuse(const char *URL)98{99CURLM *multi = NULL;100CURLMcode mc;101int running_handles = 0, numfds;102CURLMsg *msg;103CURLSH *share = NULL;104CURLU *cu;105struct curl_slist *resolve = NULL;106char resolve_buf[1024];107int msgs_in_queue;108int add_more, waits, ongoing = 0;109char *host = NULL, *port = NULL;110long http_version = CURL_HTTP_VERSION_1_1;111CURLcode result = (CURLcode)1;112113if(!URL || !libtest_arg2) {114curl_mfprintf(stderr, "need args: URL proto\n");115return (CURLcode)2;116}117118if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {119curl_mfprintf(stderr, "curl_global_init() failed\n");120return (CURLcode)3;121}122123if(!strcmp("h2", libtest_arg2))124http_version = CURL_HTTP_VERSION_2;125else if(!strcmp("h3", libtest_arg2))126http_version = CURL_HTTP_VERSION_3ONLY;127128cu = curl_url();129if(!cu) {130curl_mfprintf(stderr, "out of memory\n");131result = (CURLcode)1;132goto cleanup;133}134if(curl_url_set(cu, CURLUPART_URL, URL, 0)) {135curl_mfprintf(stderr, "not a URL: '%s'\n", URL);136goto cleanup;137}138if(curl_url_get(cu, CURLUPART_HOST, &host, 0)) {139curl_mfprintf(stderr, "could not get host of '%s'\n", URL);140goto cleanup;141}142if(curl_url_get(cu, CURLUPART_PORT, &port, 0)) {143curl_mfprintf(stderr, "could not get port of '%s'\n", URL);144goto cleanup;145}146147curl_msnprintf(resolve_buf, sizeof(resolve_buf)-1, "%s:%s:127.0.0.1",148host, port);149resolve = curl_slist_append(resolve, resolve_buf);150151multi = curl_multi_init();152if(!multi) {153curl_mfprintf(stderr, "curl_multi_init failed\n");154goto cleanup;155}156157share = curl_share_init();158if(!share) {159curl_mfprintf(stderr, "curl_share_init failed\n");160goto cleanup;161}162curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION);163164165if(!tse_add_transfer(multi, share, resolve, URL, http_version))166goto cleanup;167++ongoing;168add_more = 6;169waits = 3;170do {171mc = curl_multi_perform(multi, &running_handles);172if(mc != CURLM_OK) {173curl_mfprintf(stderr, "curl_multi_perform: %s\n",174curl_multi_strerror(mc));175goto cleanup;176}177178if(running_handles) {179mc = curl_multi_poll(multi, NULL, 0, 1000000, &numfds);180if(mc != CURLM_OK) {181curl_mfprintf(stderr, "curl_multi_poll: %s\n",182curl_multi_strerror(mc));183goto cleanup;184}185}186187if(waits) {188--waits;189}190else {191while(add_more) {192if(!tse_add_transfer(multi, share, resolve, URL, http_version))193goto cleanup;194++ongoing;195--add_more;196}197}198199/* Check for finished handles and remove. */200/* !checksrc! disable EQUALSNULL 1 */201while((msg = curl_multi_info_read(multi, &msgs_in_queue)) != NULL) {202if(msg->msg == CURLMSG_DONE) {203long status = 0;204curl_off_t xfer_id;205curl_easy_getinfo(msg->easy_handle, CURLINFO_XFER_ID, &xfer_id);206curl_easy_getinfo(msg->easy_handle, CURLINFO_RESPONSE_CODE, &status);207if(msg->data.result == CURLE_SEND_ERROR ||208msg->data.result == CURLE_RECV_ERROR) {209/* We get these if the server had a GOAWAY in transit on210* reusing a connection */211}212else if(msg->data.result) {213curl_mfprintf(stderr, "transfer #%" CURL_FORMAT_CURL_OFF_T214": failed with %d\n", xfer_id, msg->data.result);215goto cleanup;216}217else if(status != 200) {218curl_mfprintf(stderr, "transfer #%" CURL_FORMAT_CURL_OFF_T219": wrong http status %ld (expected 200)\n", xfer_id,220status);221goto cleanup;222}223curl_multi_remove_handle(multi, msg->easy_handle);224curl_easy_cleanup(msg->easy_handle);225--ongoing;226curl_mfprintf(stderr, "transfer #%" CURL_FORMAT_CURL_OFF_T" retiring "227"(%d now running)\n", xfer_id, running_handles);228}229}230231curl_mfprintf(stderr, "running_handles=%d, yet_to_start=%d\n",232running_handles, add_more);233234} while(ongoing || add_more);235236if(!tse_found_tls_session) {237curl_mfprintf(stderr, "CURLINFO_TLS_SSL_PTR not found during run\n");238result = CURLE_FAILED_INIT;239goto cleanup;240}241242curl_mfprintf(stderr, "exiting\n");243result = CURLE_OK;244245cleanup:246247if(multi) {248CURL **list = curl_multi_get_handles(multi);249if(list) {250int i;251for(i = 0; list[i]; i++) {252curl_multi_remove_handle(multi, list[i]);253curl_easy_cleanup(list[i]);254}255curl_free(list);256}257curl_multi_cleanup(multi);258}259curl_share_cleanup(share);260curl_slist_free_all(resolve);261curl_free(host);262curl_free(port);263if(cu)264curl_url_cleanup(cu);265curl_global_cleanup();266267return result;268}269270271