quickjs-tart

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

getinfo.c (18472B)


      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 
     29 #include "urldata.h"
     30 #include "getinfo.h"
     31 #include "cfilters.h"
     32 #include "vtls/vtls.h"
     33 #include "connect.h" /* Curl_getconnectinfo() */
     34 #include "progress.h"
     35 #include "curlx/strparse.h"
     36 
     37 /* The last #include files should be: */
     38 #include "curl_memory.h"
     39 #include "memdebug.h"
     40 
     41 /*
     42  * Initialize statistical and informational data.
     43  *
     44  * This function is called in curl_easy_reset, curl_easy_duphandle and at the
     45  * beginning of a perform session. It must reset the session-info variables,
     46  * in particular all variables in struct PureInfo.
     47  */
     48 CURLcode Curl_initinfo(struct Curl_easy *data)
     49 {
     50   struct Progress *pro = &data->progress;
     51   struct PureInfo *info = &data->info;
     52 
     53   pro->t_nslookup = 0;
     54   pro->t_connect = 0;
     55   pro->t_appconnect = 0;
     56   pro->t_pretransfer = 0;
     57   pro->t_posttransfer = 0;
     58   pro->t_starttransfer = 0;
     59   pro->timespent = 0;
     60   pro->t_redirect = 0;
     61   pro->is_t_startransfer_set = FALSE;
     62 
     63   info->httpcode = 0;
     64   info->httpproxycode = 0;
     65   info->httpversion = 0;
     66   info->filetime = -1; /* -1 is an illegal time and thus means unknown */
     67   info->timecond = FALSE;
     68 
     69   info->header_size = 0;
     70   info->request_size = 0;
     71   info->proxyauthavail = 0;
     72   info->httpauthavail = 0;
     73   info->proxyauthpicked = 0;
     74   info->httpauthpicked = 0;
     75   info->numconnects = 0;
     76 
     77   free(info->contenttype);
     78   info->contenttype = NULL;
     79 
     80   free(info->wouldredirect);
     81   info->wouldredirect = NULL;
     82 
     83   memset(&info->primary, 0, sizeof(info->primary));
     84   info->primary.remote_port = -1;
     85   info->primary.local_port = -1;
     86   info->retry_after = 0;
     87 
     88   info->conn_scheme = 0;
     89   info->conn_protocol = 0;
     90 
     91 #ifdef USE_SSL
     92   Curl_ssl_free_certinfo(data);
     93 #endif
     94   return CURLE_OK;
     95 }
     96 
     97 static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info,
     98                              const char **param_charp)
     99 {
    100   switch(info) {
    101   case CURLINFO_EFFECTIVE_URL:
    102     *param_charp = data->state.url ? data->state.url : "";
    103     break;
    104   case CURLINFO_EFFECTIVE_METHOD: {
    105     const char *m = data->set.str[STRING_CUSTOMREQUEST];
    106     if(!m) {
    107       if(data->set.opt_no_body)
    108         m = "HEAD";
    109 #ifndef CURL_DISABLE_HTTP
    110       else {
    111         switch(data->state.httpreq) {
    112         case HTTPREQ_POST:
    113         case HTTPREQ_POST_FORM:
    114         case HTTPREQ_POST_MIME:
    115           m = "POST";
    116           break;
    117         case HTTPREQ_PUT:
    118           m = "PUT";
    119           break;
    120         default: /* this should never happen */
    121         case HTTPREQ_GET:
    122           m = "GET";
    123           break;
    124         case HTTPREQ_HEAD:
    125           m = "HEAD";
    126           break;
    127         }
    128       }
    129 #endif
    130     }
    131     *param_charp = m;
    132   }
    133     break;
    134   case CURLINFO_CONTENT_TYPE:
    135     *param_charp = data->info.contenttype;
    136     break;
    137   case CURLINFO_PRIVATE:
    138     *param_charp = (char *) data->set.private_data;
    139     break;
    140   case CURLINFO_FTP_ENTRY_PATH:
    141     /* Return the entrypath string from the most recent connection.
    142        This pointer was copied from the connectdata structure by FTP.
    143        The actual string may be free()ed by subsequent libcurl calls so
    144        it must be copied to a safer area before the next libcurl call.
    145        Callers must never free it themselves. */
    146     *param_charp = data->state.most_recent_ftp_entrypath;
    147     break;
    148   case CURLINFO_REDIRECT_URL:
    149     /* Return the URL this request would have been redirected to if that
    150        option had been enabled! */
    151     *param_charp = data->info.wouldredirect;
    152     break;
    153   case CURLINFO_REFERER:
    154     /* Return the referrer header for this request, or NULL if unset */
    155     *param_charp = data->state.referer;
    156     break;
    157   case CURLINFO_PRIMARY_IP:
    158     /* Return the ip address of the most recent (primary) connection */
    159     *param_charp = data->info.primary.remote_ip;
    160     break;
    161   case CURLINFO_LOCAL_IP:
    162     /* Return the source/local ip address of the most recent (primary)
    163        connection */
    164     *param_charp = data->info.primary.local_ip;
    165     break;
    166   case CURLINFO_RTSP_SESSION_ID:
    167 #ifndef CURL_DISABLE_RTSP
    168     *param_charp = data->set.str[STRING_RTSP_SESSION_ID];
    169 #else
    170     *param_charp = NULL;
    171 #endif
    172     break;
    173   case CURLINFO_SCHEME:
    174     *param_charp = data->info.conn_scheme;
    175     break;
    176   case CURLINFO_CAPATH:
    177 #ifdef CURL_CA_PATH
    178     *param_charp = CURL_CA_PATH;
    179 #else
    180     *param_charp = NULL;
    181 #endif
    182     break;
    183   case CURLINFO_CAINFO:
    184 #ifdef CURL_CA_BUNDLE
    185     *param_charp = CURL_CA_BUNDLE;
    186 #else
    187     *param_charp = NULL;
    188 #endif
    189     break;
    190   default:
    191     return CURLE_UNKNOWN_OPTION;
    192   }
    193 
    194   return CURLE_OK;
    195 }
    196 
    197 static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
    198                              long *param_longp)
    199 {
    200   curl_socket_t sockfd;
    201 
    202   union {
    203     unsigned long *to_ulong;
    204     long          *to_long;
    205   } lptr;
    206 
    207 #ifdef DEBUGBUILD
    208   const char *timestr = getenv("CURL_TIME");
    209   if(timestr) {
    210     curl_off_t val;
    211     curlx_str_number(&timestr, &val, TIME_T_MAX);
    212     switch(info) {
    213     case CURLINFO_LOCAL_PORT:
    214       *param_longp = (long)val;
    215       return CURLE_OK;
    216     default:
    217       break;
    218     }
    219   }
    220   /* use another variable for this to allow different values */
    221   timestr = getenv("CURL_DEBUG_SIZE");
    222   if(timestr) {
    223     curl_off_t val;
    224     curlx_str_number(&timestr, &val, LONG_MAX);
    225     switch(info) {
    226     case CURLINFO_HEADER_SIZE:
    227     case CURLINFO_REQUEST_SIZE:
    228       *param_longp = (long)val;
    229       return CURLE_OK;
    230     default:
    231       break;
    232     }
    233   }
    234 #endif
    235 
    236   switch(info) {
    237   case CURLINFO_RESPONSE_CODE:
    238     *param_longp = data->info.httpcode;
    239     break;
    240   case CURLINFO_HTTP_CONNECTCODE:
    241     *param_longp = data->info.httpproxycode;
    242     break;
    243   case CURLINFO_FILETIME:
    244     if(data->info.filetime > LONG_MAX)
    245       *param_longp = LONG_MAX;
    246 #if !defined(MSDOS) && !defined(__AMIGA__)
    247     else if(data->info.filetime < LONG_MIN)
    248       *param_longp = LONG_MIN;
    249 #endif
    250     else
    251       *param_longp = (long)data->info.filetime;
    252     break;
    253   case CURLINFO_HEADER_SIZE:
    254     *param_longp = (long)data->info.header_size;
    255     break;
    256   case CURLINFO_REQUEST_SIZE:
    257     *param_longp = (long)data->info.request_size;
    258     break;
    259   case CURLINFO_SSL_VERIFYRESULT:
    260     *param_longp = data->set.ssl.certverifyresult;
    261     break;
    262   case CURLINFO_PROXY_SSL_VERIFYRESULT:
    263 #ifndef CURL_DISABLE_PROXY
    264     *param_longp = data->set.proxy_ssl.certverifyresult;
    265 #else
    266     *param_longp = 0;
    267 #endif
    268     break;
    269   case CURLINFO_REDIRECT_COUNT:
    270     *param_longp = data->state.followlocation;
    271     break;
    272   case CURLINFO_HTTPAUTH_AVAIL:
    273     lptr.to_long = param_longp;
    274     *lptr.to_ulong = data->info.httpauthavail;
    275     break;
    276   case CURLINFO_PROXYAUTH_AVAIL:
    277     lptr.to_long = param_longp;
    278     *lptr.to_ulong = data->info.proxyauthavail;
    279     break;
    280   case CURLINFO_HTTPAUTH_USED:
    281     lptr.to_long = param_longp;
    282     *lptr.to_ulong = data->info.httpauthpicked;
    283     break;
    284   case CURLINFO_PROXYAUTH_USED:
    285     lptr.to_long = param_longp;
    286     *lptr.to_ulong = data->info.proxyauthpicked;
    287     break;
    288   case CURLINFO_OS_ERRNO:
    289     *param_longp = data->state.os_errno;
    290     break;
    291   case CURLINFO_NUM_CONNECTS:
    292     *param_longp = data->info.numconnects;
    293     break;
    294   case CURLINFO_LASTSOCKET:
    295     sockfd = Curl_getconnectinfo(data, NULL);
    296 
    297     /* note: this is not a good conversion for systems with 64-bit sockets and
    298        32-bit longs */
    299     if(sockfd != CURL_SOCKET_BAD)
    300       *param_longp = (long)sockfd;
    301     else
    302       /* this interface is documented to return -1 in case of badness, which
    303          may not be the same as the CURL_SOCKET_BAD value */
    304       *param_longp = -1;
    305     break;
    306   case CURLINFO_PRIMARY_PORT:
    307     /* Return the (remote) port of the most recent (primary) connection */
    308     *param_longp = data->info.primary.remote_port;
    309     break;
    310   case CURLINFO_LOCAL_PORT:
    311     /* Return the local port of the most recent (primary) connection */
    312     *param_longp = data->info.primary.local_port;
    313     break;
    314   case CURLINFO_PROXY_ERROR:
    315     *param_longp = (long)data->info.pxcode;
    316     break;
    317   case CURLINFO_CONDITION_UNMET:
    318     if(data->info.httpcode == 304)
    319       *param_longp = 1L;
    320     else
    321       /* return if the condition prevented the document to get transferred */
    322       *param_longp = data->info.timecond ? 1L : 0L;
    323     break;
    324 #ifndef CURL_DISABLE_RTSP
    325   case CURLINFO_RTSP_CLIENT_CSEQ:
    326     *param_longp = data->state.rtsp_next_client_CSeq;
    327     break;
    328   case CURLINFO_RTSP_SERVER_CSEQ:
    329     *param_longp = data->state.rtsp_next_server_CSeq;
    330     break;
    331   case CURLINFO_RTSP_CSEQ_RECV:
    332     *param_longp = data->state.rtsp_CSeq_recv;
    333     break;
    334 #else
    335   case CURLINFO_RTSP_CLIENT_CSEQ:
    336   case CURLINFO_RTSP_SERVER_CSEQ:
    337   case CURLINFO_RTSP_CSEQ_RECV:
    338     *param_longp = 0;
    339     break;
    340 #endif
    341   case CURLINFO_HTTP_VERSION:
    342     switch(data->info.httpversion) {
    343     case 10:
    344       *param_longp = CURL_HTTP_VERSION_1_0;
    345       break;
    346     case 11:
    347       *param_longp = CURL_HTTP_VERSION_1_1;
    348       break;
    349     case 20:
    350       *param_longp = CURL_HTTP_VERSION_2_0;
    351       break;
    352     case 30:
    353       *param_longp = CURL_HTTP_VERSION_3;
    354       break;
    355     default:
    356       *param_longp = CURL_HTTP_VERSION_NONE;
    357       break;
    358     }
    359     break;
    360   case CURLINFO_PROTOCOL:
    361     *param_longp = (long)data->info.conn_protocol;
    362     break;
    363   case CURLINFO_USED_PROXY:
    364     *param_longp =
    365 #ifdef CURL_DISABLE_PROXY
    366       0
    367 #else
    368       data->info.used_proxy
    369 #endif
    370       ;
    371     break;
    372   default:
    373     return CURLE_UNKNOWN_OPTION;
    374   }
    375 
    376   return CURLE_OK;
    377 }
    378 
    379 #define DOUBLE_SECS(x) (double)(x)/1000000
    380 
    381 static CURLcode getinfo_offt(struct Curl_easy *data, CURLINFO info,
    382                              curl_off_t *param_offt)
    383 {
    384 #ifdef DEBUGBUILD
    385   const char *timestr = getenv("CURL_TIME");
    386   if(timestr) {
    387     curl_off_t val;
    388     curlx_str_number(&timestr, &val, CURL_OFF_T_MAX);
    389 
    390     switch(info) {
    391     case CURLINFO_TOTAL_TIME_T:
    392     case CURLINFO_NAMELOOKUP_TIME_T:
    393     case CURLINFO_CONNECT_TIME_T:
    394     case CURLINFO_APPCONNECT_TIME_T:
    395     case CURLINFO_PRETRANSFER_TIME_T:
    396     case CURLINFO_POSTTRANSFER_TIME_T:
    397     case CURLINFO_QUEUE_TIME_T:
    398     case CURLINFO_STARTTRANSFER_TIME_T:
    399     case CURLINFO_REDIRECT_TIME_T:
    400     case CURLINFO_SPEED_DOWNLOAD_T:
    401     case CURLINFO_SPEED_UPLOAD_T:
    402       *param_offt = (curl_off_t)val;
    403       return CURLE_OK;
    404     default:
    405       break;
    406     }
    407   }
    408 #endif
    409   switch(info) {
    410   case CURLINFO_FILETIME_T:
    411     *param_offt = (curl_off_t)data->info.filetime;
    412     break;
    413   case CURLINFO_SIZE_UPLOAD_T:
    414     *param_offt = data->progress.ul.cur_size;
    415     break;
    416   case CURLINFO_SIZE_DOWNLOAD_T:
    417     *param_offt = data->progress.dl.cur_size;
    418     break;
    419   case CURLINFO_SPEED_DOWNLOAD_T:
    420     *param_offt = data->progress.dl.speed;
    421     break;
    422   case CURLINFO_SPEED_UPLOAD_T:
    423     *param_offt = data->progress.ul.speed;
    424     break;
    425   case CURLINFO_CONTENT_LENGTH_DOWNLOAD_T:
    426     *param_offt = data->progress.dl_size_known ?
    427       data->progress.dl.total_size : -1;
    428     break;
    429   case CURLINFO_CONTENT_LENGTH_UPLOAD_T:
    430     *param_offt = data->progress.ul_size_known ?
    431       data->progress.ul.total_size : -1;
    432     break;
    433    case CURLINFO_TOTAL_TIME_T:
    434     *param_offt = data->progress.timespent;
    435     break;
    436   case CURLINFO_NAMELOOKUP_TIME_T:
    437     *param_offt = data->progress.t_nslookup;
    438     break;
    439   case CURLINFO_CONNECT_TIME_T:
    440     *param_offt = data->progress.t_connect;
    441     break;
    442   case CURLINFO_APPCONNECT_TIME_T:
    443     *param_offt = data->progress.t_appconnect;
    444     break;
    445   case CURLINFO_PRETRANSFER_TIME_T:
    446     *param_offt = data->progress.t_pretransfer;
    447     break;
    448   case CURLINFO_POSTTRANSFER_TIME_T:
    449     *param_offt = data->progress.t_posttransfer;
    450     break;
    451   case CURLINFO_STARTTRANSFER_TIME_T:
    452     *param_offt = data->progress.t_starttransfer;
    453     break;
    454   case CURLINFO_QUEUE_TIME_T:
    455     *param_offt = data->progress.t_postqueue;
    456     break;
    457   case CURLINFO_REDIRECT_TIME_T:
    458     *param_offt = data->progress.t_redirect;
    459     break;
    460   case CURLINFO_RETRY_AFTER:
    461     *param_offt = data->info.retry_after;
    462     break;
    463   case CURLINFO_XFER_ID:
    464     *param_offt = data->id;
    465     break;
    466   case CURLINFO_CONN_ID:
    467     *param_offt = data->conn ?
    468       data->conn->connection_id : data->state.recent_conn_id;
    469     break;
    470   case CURLINFO_EARLYDATA_SENT_T:
    471     *param_offt = data->progress.earlydata_sent;
    472     break;
    473   default:
    474     return CURLE_UNKNOWN_OPTION;
    475   }
    476 
    477   return CURLE_OK;
    478 }
    479 
    480 static CURLcode getinfo_double(struct Curl_easy *data, CURLINFO info,
    481                                double *param_doublep)
    482 {
    483 #ifdef DEBUGBUILD
    484   const char *timestr = getenv("CURL_TIME");
    485   if(timestr) {
    486     curl_off_t val;
    487     curlx_str_number(&timestr, &val, CURL_OFF_T_MAX);
    488 
    489     switch(info) {
    490     case CURLINFO_TOTAL_TIME:
    491     case CURLINFO_NAMELOOKUP_TIME:
    492     case CURLINFO_CONNECT_TIME:
    493     case CURLINFO_APPCONNECT_TIME:
    494     case CURLINFO_PRETRANSFER_TIME:
    495     case CURLINFO_STARTTRANSFER_TIME:
    496     case CURLINFO_REDIRECT_TIME:
    497     case CURLINFO_SPEED_DOWNLOAD:
    498     case CURLINFO_SPEED_UPLOAD:
    499       *param_doublep = (double)val;
    500       return CURLE_OK;
    501     default:
    502       break;
    503     }
    504   }
    505 #endif
    506   switch(info) {
    507   case CURLINFO_TOTAL_TIME:
    508     *param_doublep = DOUBLE_SECS(data->progress.timespent);
    509     break;
    510   case CURLINFO_NAMELOOKUP_TIME:
    511     *param_doublep = DOUBLE_SECS(data->progress.t_nslookup);
    512     break;
    513   case CURLINFO_CONNECT_TIME:
    514     *param_doublep = DOUBLE_SECS(data->progress.t_connect);
    515     break;
    516   case CURLINFO_APPCONNECT_TIME:
    517     *param_doublep = DOUBLE_SECS(data->progress.t_appconnect);
    518     break;
    519   case CURLINFO_PRETRANSFER_TIME:
    520     *param_doublep = DOUBLE_SECS(data->progress.t_pretransfer);
    521     break;
    522   case CURLINFO_STARTTRANSFER_TIME:
    523     *param_doublep = DOUBLE_SECS(data->progress.t_starttransfer);
    524     break;
    525   case CURLINFO_SIZE_UPLOAD:
    526     *param_doublep = (double)data->progress.ul.cur_size;
    527     break;
    528   case CURLINFO_SIZE_DOWNLOAD:
    529     *param_doublep = (double)data->progress.dl.cur_size;
    530     break;
    531   case CURLINFO_SPEED_DOWNLOAD:
    532     *param_doublep = (double)data->progress.dl.speed;
    533     break;
    534   case CURLINFO_SPEED_UPLOAD:
    535     *param_doublep = (double)data->progress.ul.speed;
    536     break;
    537   case CURLINFO_CONTENT_LENGTH_DOWNLOAD:
    538     *param_doublep = data->progress.dl_size_known ?
    539       (double)data->progress.dl.total_size : -1;
    540     break;
    541   case CURLINFO_CONTENT_LENGTH_UPLOAD:
    542     *param_doublep = data->progress.ul_size_known ?
    543       (double)data->progress.ul.total_size : -1;
    544     break;
    545   case CURLINFO_REDIRECT_TIME:
    546     *param_doublep = DOUBLE_SECS(data->progress.t_redirect);
    547     break;
    548 
    549   default:
    550     return CURLE_UNKNOWN_OPTION;
    551   }
    552 
    553   return CURLE_OK;
    554 }
    555 
    556 static CURLcode getinfo_slist(struct Curl_easy *data, CURLINFO info,
    557                               struct curl_slist **param_slistp)
    558 {
    559   union {
    560     struct curl_certinfo *to_certinfo;
    561     struct curl_slist    *to_slist;
    562   } ptr;
    563 
    564   switch(info) {
    565   case CURLINFO_SSL_ENGINES:
    566     *param_slistp = Curl_ssl_engines_list(data);
    567     break;
    568   case CURLINFO_COOKIELIST:
    569     *param_slistp = Curl_cookie_list(data);
    570     break;
    571   case CURLINFO_CERTINFO:
    572     /* Return the a pointer to the certinfo struct. Not really an slist
    573        pointer but we can pretend it is here */
    574     ptr.to_certinfo = &data->info.certs;
    575     *param_slistp = ptr.to_slist;
    576     break;
    577   case CURLINFO_TLS_SESSION:
    578   case CURLINFO_TLS_SSL_PTR:
    579     {
    580       struct curl_tlssessioninfo **tsip = (struct curl_tlssessioninfo **)
    581                                           param_slistp;
    582       struct curl_tlssessioninfo *tsi = &data->tsi;
    583 
    584       /* we are exposing a pointer to internal memory with unknown
    585        * lifetime here. */
    586       *tsip = tsi;
    587       if(!Curl_conn_get_ssl_info(data, data->conn, FIRSTSOCKET, tsi)) {
    588         tsi->backend = Curl_ssl_backend();
    589         tsi->internals = NULL;
    590       }
    591     }
    592     break;
    593   default:
    594     return CURLE_UNKNOWN_OPTION;
    595   }
    596 
    597   return CURLE_OK;
    598 }
    599 
    600 static CURLcode getinfo_socket(struct Curl_easy *data, CURLINFO info,
    601                                curl_socket_t *param_socketp)
    602 {
    603   switch(info) {
    604   case CURLINFO_ACTIVESOCKET:
    605     *param_socketp = Curl_getconnectinfo(data, NULL);
    606     break;
    607   default:
    608     return CURLE_UNKNOWN_OPTION;
    609   }
    610 
    611   return CURLE_OK;
    612 }
    613 
    614 CURLcode Curl_getinfo(struct Curl_easy *data, CURLINFO info, ...)
    615 {
    616   va_list arg;
    617   long *param_longp = NULL;
    618   double *param_doublep = NULL;
    619   curl_off_t *param_offt = NULL;
    620   const char **param_charp = NULL;
    621   struct curl_slist **param_slistp = NULL;
    622   curl_socket_t *param_socketp = NULL;
    623   int type;
    624   CURLcode result = CURLE_UNKNOWN_OPTION;
    625 
    626   if(!data)
    627     return CURLE_BAD_FUNCTION_ARGUMENT;
    628 
    629   va_start(arg, info);
    630 
    631   type = CURLINFO_TYPEMASK & (int)info;
    632   switch(type) {
    633   case CURLINFO_STRING:
    634     param_charp = va_arg(arg, const char **);
    635     if(param_charp)
    636       result = getinfo_char(data, info, param_charp);
    637     break;
    638   case CURLINFO_LONG:
    639     param_longp = va_arg(arg, long *);
    640     if(param_longp)
    641       result = getinfo_long(data, info, param_longp);
    642     break;
    643   case CURLINFO_DOUBLE:
    644     param_doublep = va_arg(arg, double *);
    645     if(param_doublep)
    646       result = getinfo_double(data, info, param_doublep);
    647     break;
    648   case CURLINFO_OFF_T:
    649     param_offt = va_arg(arg, curl_off_t *);
    650     if(param_offt)
    651       result = getinfo_offt(data, info, param_offt);
    652     break;
    653   case CURLINFO_SLIST:
    654     param_slistp = va_arg(arg, struct curl_slist **);
    655     if(param_slistp)
    656       result = getinfo_slist(data, info, param_slistp);
    657     break;
    658   case CURLINFO_SOCKET:
    659     param_socketp = va_arg(arg, curl_socket_t *);
    660     if(param_socketp)
    661       result = getinfo_socket(data, info, param_socketp);
    662     break;
    663   default:
    664     break;
    665   }
    666 
    667   va_end(arg);
    668 
    669   return result;
    670 }