quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

tls_session_reuse.c (7898B)


      1 /***************************************************************************
      2  *                                  _   _ ____  _
      3  *  Project                     ___| | | |  _ \| |
      4  *                             / __| | | | |_) | |
      5  *                            | (__| |_| |  _ <| |___
      6  *                             \___|\___/|_| \_\_____|
      7  *
      8  * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
      9  *
     10  * This software is licensed as described in the file COPYING, which
     11  * you should have received as part of this distribution. The terms
     12  * are also available at https://curl.se/docs/copyright.html.
     13  *
     14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
     15  * copies of the Software, and permit persons to whom the Software is
     16  * furnished to do so, under the terms of the COPYING file.
     17  *
     18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
     19  * KIND, either express or implied.
     20  *
     21  * SPDX-License-Identifier: curl
     22  *
     23  ***************************************************************************/
     24 #include "first.h"
     25 
     26 static int tse_found_tls_session = FALSE;
     27 
     28 static size_t write_tse_cb(char *ptr, size_t size, size_t nmemb, void *opaque)
     29 {
     30   CURL *easy = opaque;
     31   (void)ptr;
     32   if(!tse_found_tls_session) {
     33     struct curl_tlssessioninfo *tlssession;
     34     CURLcode rc;
     35 
     36     rc = curl_easy_getinfo(easy, CURLINFO_TLS_SSL_PTR, &tlssession);
     37     if(rc) {
     38       curl_mfprintf(stderr, "curl_easy_getinfo(CURLINFO_TLS_SSL_PTR) "
     39                     "failed: %s\n", curl_easy_strerror(rc));
     40       return rc;
     41     }
     42     if(tlssession->backend == CURLSSLBACKEND_NONE) {
     43       curl_mfprintf(stderr, "curl_easy_getinfo(CURLINFO_TLS_SSL_PTR) "
     44                     "gave no backend\n");
     45       return CURLE_FAILED_INIT;
     46     }
     47     if(!tlssession->internals) {
     48       curl_mfprintf(stderr, "curl_easy_getinfo(CURLINFO_TLS_SSL_PTR) "
     49                     "missing\n");
     50       return CURLE_FAILED_INIT;
     51     }
     52     tse_found_tls_session = TRUE;
     53   }
     54   return size * nmemb;
     55 }
     56 
     57 static CURL *tse_add_transfer(CURLM *multi, CURLSH *share,
     58                               struct curl_slist *resolve,
     59                               const char *url, long http_version)
     60 {
     61   CURL *easy;
     62   CURLMcode mc;
     63 
     64   easy = curl_easy_init();
     65   if(!easy) {
     66     curl_mfprintf(stderr, "curl_easy_init failed\n");
     67     return NULL;
     68   }
     69   curl_easy_setopt(easy, CURLOPT_VERBOSE, 1L);
     70   curl_easy_setopt(easy, CURLOPT_DEBUGFUNCTION, debug_cb);
     71   curl_easy_setopt(easy, CURLOPT_URL, url);
     72   curl_easy_setopt(easy, CURLOPT_SHARE, share);
     73   curl_easy_setopt(easy, CURLOPT_NOSIGNAL, 1L);
     74   curl_easy_setopt(easy, CURLOPT_AUTOREFERER, 1L);
     75   curl_easy_setopt(easy, CURLOPT_FAILONERROR, 1L);
     76   curl_easy_setopt(easy, CURLOPT_HTTP_VERSION, http_version);
     77   curl_easy_setopt(easy, CURLOPT_WRITEFUNCTION, write_tse_cb);
     78   curl_easy_setopt(easy, CURLOPT_WRITEDATA, easy);
     79   curl_easy_setopt(easy, CURLOPT_HTTPGET, 1L);
     80   curl_easy_setopt(easy, CURLOPT_SSL_VERIFYPEER, 0L);
     81   if(resolve)
     82     curl_easy_setopt(easy, CURLOPT_RESOLVE, resolve);
     83 
     84 
     85   mc = curl_multi_add_handle(multi, easy);
     86   if(mc != CURLM_OK) {
     87     curl_mfprintf(stderr, "curl_multi_add_handle: %s\n",
     88                   curl_multi_strerror(mc));
     89     curl_easy_cleanup(easy);
     90     return NULL;
     91   }
     92   return easy;
     93 }
     94 
     95 static int test_tls_session_reuse(int argc, char *argv[])
     96 {
     97   const char *url;
     98   CURLM *multi = NULL;
     99   CURLMcode mc;
    100   int running_handles = 0, numfds;
    101   CURLMsg *msg;
    102   CURLSH *share = NULL;
    103   CURLU *cu;
    104   struct curl_slist *resolve = NULL;
    105   char resolve_buf[1024];
    106   int msgs_in_queue;
    107   int add_more, waits, ongoing = 0;
    108   char *host = NULL, *port = NULL;
    109   int http_version = CURL_HTTP_VERSION_1_1;
    110   int exitcode = 1;
    111 
    112   if(argc != 3) {
    113     curl_mfprintf(stderr, "%s proto URL\n", argv[0]);
    114     return 2;
    115   }
    116 
    117   if(!strcmp("h2", argv[1]))
    118     http_version = CURL_HTTP_VERSION_2;
    119   else if(!strcmp("h3", argv[1]))
    120     http_version = CURL_HTTP_VERSION_3ONLY;
    121 
    122   url = argv[2];
    123   cu = curl_url();
    124   if(!cu) {
    125     curl_mfprintf(stderr, "out of memory\n");
    126     return 1;
    127   }
    128   if(curl_url_set(cu, CURLUPART_URL, url, 0)) {
    129     curl_mfprintf(stderr, "not a URL: '%s'\n", url);
    130     goto cleanup;
    131   }
    132   if(curl_url_get(cu, CURLUPART_HOST, &host, 0)) {
    133     curl_mfprintf(stderr, "could not get host of '%s'\n", url);
    134     goto cleanup;
    135   }
    136   if(curl_url_get(cu, CURLUPART_PORT, &port, 0)) {
    137     curl_mfprintf(stderr, "could not get port of '%s'\n", url);
    138     goto cleanup;
    139   }
    140 
    141   curl_msnprintf(resolve_buf, sizeof(resolve_buf)-1, "%s:%s:127.0.0.1",
    142                  host, port);
    143   resolve = curl_slist_append(resolve, resolve_buf);
    144 
    145   multi = curl_multi_init();
    146   if(!multi) {
    147     curl_mfprintf(stderr, "curl_multi_init failed\n");
    148     goto cleanup;
    149   }
    150 
    151   share = curl_share_init();
    152   if(!share) {
    153     curl_mfprintf(stderr, "curl_share_init failed\n");
    154     goto cleanup;
    155   }
    156   curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION);
    157 
    158 
    159   if(!tse_add_transfer(multi, share, resolve, url, http_version))
    160     goto cleanup;
    161   ++ongoing;
    162   add_more = 6;
    163   waits = 3;
    164   do {
    165     mc = curl_multi_perform(multi, &running_handles);
    166     if(mc != CURLM_OK) {
    167       curl_mfprintf(stderr, "curl_multi_perform: %s\n",
    168                     curl_multi_strerror(mc));
    169       goto cleanup;
    170     }
    171 
    172     if(running_handles) {
    173       mc = curl_multi_poll(multi, NULL, 0, 1000000, &numfds);
    174       if(mc != CURLM_OK) {
    175         curl_mfprintf(stderr, "curl_multi_poll: %s\n",
    176                       curl_multi_strerror(mc));
    177         goto cleanup;
    178       }
    179     }
    180 
    181     if(waits) {
    182       --waits;
    183     }
    184     else {
    185       while(add_more) {
    186         if(!tse_add_transfer(multi, share, resolve, url, http_version))
    187           goto cleanup;
    188         ++ongoing;
    189         --add_more;
    190       }
    191     }
    192 
    193     /* Check for finished handles and remove. */
    194     /* !checksrc! disable EQUALSNULL 1 */
    195     while((msg = curl_multi_info_read(multi, &msgs_in_queue)) != NULL) {
    196       if(msg->msg == CURLMSG_DONE) {
    197         long status = 0;
    198         curl_off_t xfer_id;
    199         curl_easy_getinfo(msg->easy_handle, CURLINFO_XFER_ID, &xfer_id);
    200         curl_easy_getinfo(msg->easy_handle, CURLINFO_RESPONSE_CODE, &status);
    201         if(msg->data.result == CURLE_SEND_ERROR ||
    202             msg->data.result == CURLE_RECV_ERROR) {
    203           /* We get these if the server had a GOAWAY in transit on
    204            * re-using a connection */
    205         }
    206         else if(msg->data.result) {
    207           curl_mfprintf(stderr, "transfer #%" CURL_FORMAT_CURL_OFF_T
    208                         ": failed with %d\n", xfer_id, msg->data.result);
    209           goto cleanup;
    210         }
    211         else if(status != 200) {
    212           curl_mfprintf(stderr, "transfer #%" CURL_FORMAT_CURL_OFF_T
    213                         ": wrong http status %ld (expected 200)\n", xfer_id,
    214                         status);
    215           goto cleanup;
    216         }
    217         curl_multi_remove_handle(multi, msg->easy_handle);
    218         curl_easy_cleanup(msg->easy_handle);
    219         --ongoing;
    220         curl_mfprintf(stderr, "transfer #%" CURL_FORMAT_CURL_OFF_T" retiring "
    221                       "(%d now running)\n", xfer_id, running_handles);
    222       }
    223     }
    224 
    225     curl_mfprintf(stderr, "running_handles=%d, yet_to_start=%d\n",
    226                   running_handles, add_more);
    227 
    228   } while(ongoing || add_more);
    229 
    230   if(!tse_found_tls_session) {
    231     curl_mfprintf(stderr, "CURLINFO_TLS_SSL_PTR not found during run\n");
    232     exitcode = CURLE_FAILED_INIT;
    233     goto cleanup;
    234   }
    235 
    236   curl_mfprintf(stderr, "exiting\n");
    237   exitcode = 0;
    238 
    239 cleanup:
    240 
    241   if(multi) {
    242     CURL **list = curl_multi_get_handles(multi);
    243     if(list) {
    244       int i;
    245       for(i = 0; list[i]; i++) {
    246         curl_multi_remove_handle(multi, list[i]);
    247         curl_easy_cleanup(list[i]);
    248       }
    249       curl_free(list);
    250     }
    251     curl_multi_cleanup(multi);
    252   }
    253   curl_share_cleanup(share);
    254   curl_slist_free_all(resolve);
    255   curl_free(host);
    256   curl_free(port);
    257   curl_url_cleanup(cu);
    258 
    259   return exitcode;
    260 }