quickjs-tart

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

share.c (7777B)


      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 
     25 #include "curl_setup.h"
     26 
     27 #include <curl/curl.h>
     28 #include "urldata.h"
     29 #include "connect.h"
     30 #include "share.h"
     31 #include "psl.h"
     32 #include "vtls/vtls.h"
     33 #include "vtls/vtls_scache.h"
     34 #include "hsts.h"
     35 #include "url.h"
     36 
     37 /* The last 3 #include files should be in this order */
     38 #include "curl_printf.h"
     39 #include "curl_memory.h"
     40 #include "memdebug.h"
     41 
     42 CURLSH *
     43 curl_share_init(void)
     44 {
     45   struct Curl_share *share = calloc(1, sizeof(struct Curl_share));
     46   if(share) {
     47     share->magic = CURL_GOOD_SHARE;
     48     share->specifier |= (1 << CURL_LOCK_DATA_SHARE);
     49     Curl_dnscache_init(&share->dnscache, 23);
     50     share->admin = curl_easy_init();
     51     if(!share->admin) {
     52       free(share);
     53       return NULL;
     54     }
     55     /* admin handles have mid 0 */
     56     share->admin->mid = 0;
     57     share->admin->state.internal = TRUE;
     58 #ifdef DEBUGBUILD
     59     if(getenv("CURL_DEBUG"))
     60       share->admin->set.verbose = TRUE;
     61 #endif
     62   }
     63 
     64   return share;
     65 }
     66 
     67 #undef curl_share_setopt
     68 CURLSHcode
     69 curl_share_setopt(CURLSH *sh, CURLSHoption option, ...)
     70 {
     71   va_list param;
     72   int type;
     73   curl_lock_function lockfunc;
     74   curl_unlock_function unlockfunc;
     75   void *ptr;
     76   CURLSHcode res = CURLSHE_OK;
     77   struct Curl_share *share = sh;
     78 
     79   if(!GOOD_SHARE_HANDLE(share))
     80     return CURLSHE_INVALID;
     81 
     82   if(share->dirty)
     83     /* do not allow setting options while one or more handles are already
     84        using this share */
     85     return CURLSHE_IN_USE;
     86 
     87   va_start(param, option);
     88 
     89   switch(option) {
     90   case CURLSHOPT_SHARE:
     91     /* this is a type this share will share */
     92     type = va_arg(param, int);
     93 
     94     switch(type) {
     95     case CURL_LOCK_DATA_DNS:
     96       break;
     97 
     98     case CURL_LOCK_DATA_COOKIE:
     99 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
    100       if(!share->cookies) {
    101         share->cookies = Curl_cookie_init(NULL, NULL, NULL, TRUE);
    102         if(!share->cookies)
    103           res = CURLSHE_NOMEM;
    104       }
    105 #else   /* CURL_DISABLE_HTTP */
    106       res = CURLSHE_NOT_BUILT_IN;
    107 #endif
    108       break;
    109 
    110     case CURL_LOCK_DATA_HSTS:
    111 #ifndef CURL_DISABLE_HSTS
    112       if(!share->hsts) {
    113         share->hsts = Curl_hsts_init();
    114         if(!share->hsts)
    115           res = CURLSHE_NOMEM;
    116       }
    117 #else   /* CURL_DISABLE_HSTS */
    118       res = CURLSHE_NOT_BUILT_IN;
    119 #endif
    120       break;
    121 
    122     case CURL_LOCK_DATA_SSL_SESSION:
    123 #ifdef USE_SSL
    124       if(!share->ssl_scache) {
    125         /* There is no way (yet) for the application to configure the
    126          * session cache size, shared between many transfers. As for curl
    127          * itself, a high session count will impact startup time. Also, the
    128          * scache is not optimized for several hundreds of peers. So,
    129          * keep it at a reasonable level. */
    130         if(Curl_ssl_scache_create(25, 2, &share->ssl_scache))
    131           res = CURLSHE_NOMEM;
    132       }
    133 #else
    134       res = CURLSHE_NOT_BUILT_IN;
    135 #endif
    136       break;
    137 
    138     case CURL_LOCK_DATA_CONNECT:
    139       /* It is safe to set this option several times on a share. */
    140       if(!share->cpool.initialised) {
    141         Curl_cpool_init(&share->cpool, share->admin, share, 103);
    142       }
    143       break;
    144 
    145     case CURL_LOCK_DATA_PSL:
    146 #ifndef USE_LIBPSL
    147       res = CURLSHE_NOT_BUILT_IN;
    148 #endif
    149       break;
    150 
    151     default:
    152       res = CURLSHE_BAD_OPTION;
    153     }
    154     if(!res)
    155       share->specifier |= (unsigned int)(1 << type);
    156     break;
    157 
    158   case CURLSHOPT_UNSHARE:
    159     /* this is a type this share will no longer share */
    160     type = va_arg(param, int);
    161     share->specifier &= ~(unsigned int)(1 << type);
    162     switch(type) {
    163     case CURL_LOCK_DATA_DNS:
    164       break;
    165 
    166     case CURL_LOCK_DATA_COOKIE:
    167 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
    168       if(share->cookies) {
    169         Curl_cookie_cleanup(share->cookies);
    170         share->cookies = NULL;
    171       }
    172 #else   /* CURL_DISABLE_HTTP */
    173       res = CURLSHE_NOT_BUILT_IN;
    174 #endif
    175       break;
    176 
    177     case CURL_LOCK_DATA_HSTS:
    178 #ifndef CURL_DISABLE_HSTS
    179       if(share->hsts) {
    180         Curl_hsts_cleanup(&share->hsts);
    181       }
    182 #else   /* CURL_DISABLE_HSTS */
    183       res = CURLSHE_NOT_BUILT_IN;
    184 #endif
    185       break;
    186 
    187     case CURL_LOCK_DATA_SSL_SESSION:
    188 #ifdef USE_SSL
    189       if(share->ssl_scache) {
    190         Curl_ssl_scache_destroy(share->ssl_scache);
    191         share->ssl_scache = NULL;
    192       }
    193 #else
    194       res = CURLSHE_NOT_BUILT_IN;
    195 #endif
    196       break;
    197 
    198     case CURL_LOCK_DATA_CONNECT:
    199       break;
    200 
    201     default:
    202       res = CURLSHE_BAD_OPTION;
    203       break;
    204     }
    205     break;
    206 
    207   case CURLSHOPT_LOCKFUNC:
    208     lockfunc = va_arg(param, curl_lock_function);
    209     share->lockfunc = lockfunc;
    210     break;
    211 
    212   case CURLSHOPT_UNLOCKFUNC:
    213     unlockfunc = va_arg(param, curl_unlock_function);
    214     share->unlockfunc = unlockfunc;
    215     break;
    216 
    217   case CURLSHOPT_USERDATA:
    218     ptr = va_arg(param, void *);
    219     share->clientdata = ptr;
    220     break;
    221 
    222   default:
    223     res = CURLSHE_BAD_OPTION;
    224     break;
    225   }
    226 
    227   va_end(param);
    228 
    229   return res;
    230 }
    231 
    232 CURLSHcode
    233 curl_share_cleanup(CURLSH *sh)
    234 {
    235   struct Curl_share *share = sh;
    236   if(!GOOD_SHARE_HANDLE(share))
    237     return CURLSHE_INVALID;
    238 
    239   if(share->lockfunc)
    240     share->lockfunc(NULL, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE,
    241                     share->clientdata);
    242 
    243   if(share->dirty) {
    244     if(share->unlockfunc)
    245       share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata);
    246     return CURLSHE_IN_USE;
    247   }
    248 
    249   if(share->specifier & (1 << CURL_LOCK_DATA_CONNECT)) {
    250     Curl_cpool_destroy(&share->cpool);
    251   }
    252 
    253   Curl_dnscache_destroy(&share->dnscache);
    254 
    255 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
    256   Curl_cookie_cleanup(share->cookies);
    257 #endif
    258 
    259 #ifndef CURL_DISABLE_HSTS
    260   Curl_hsts_cleanup(&share->hsts);
    261 #endif
    262 
    263 #ifdef USE_SSL
    264   if(share->ssl_scache) {
    265     Curl_ssl_scache_destroy(share->ssl_scache);
    266     share->ssl_scache = NULL;
    267   }
    268 #endif
    269 
    270   Curl_psl_destroy(&share->psl);
    271   Curl_close(&share->admin);
    272 
    273   if(share->unlockfunc)
    274     share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata);
    275   share->magic = 0;
    276   free(share);
    277 
    278   return CURLSHE_OK;
    279 }
    280 
    281 
    282 CURLSHcode
    283 Curl_share_lock(struct Curl_easy *data, curl_lock_data type,
    284                 curl_lock_access accesstype)
    285 {
    286   struct Curl_share *share = data->share;
    287 
    288   if(!share)
    289     return CURLSHE_INVALID;
    290 
    291   if(share->specifier & (unsigned int)(1 << type)) {
    292     if(share->lockfunc) /* only call this if set! */
    293       share->lockfunc(data, type, accesstype, share->clientdata);
    294   }
    295   /* else if we do not share this, pretend successful lock */
    296 
    297   return CURLSHE_OK;
    298 }
    299 
    300 CURLSHcode
    301 Curl_share_unlock(struct Curl_easy *data, curl_lock_data type)
    302 {
    303   struct Curl_share *share = data->share;
    304 
    305   if(!share)
    306     return CURLSHE_INVALID;
    307 
    308   if(share->specifier & (unsigned int)(1 << type)) {
    309     if(share->unlockfunc) /* only call this if set! */
    310       share->unlockfunc (data, type, share->clientdata);
    311   }
    312 
    313   return CURLSHE_OK;
    314 }