Annotation of embedaddon/curl/lib/getinfo.c, revision 1.1.1.1

1.1       misho       1: /***************************************************************************
                      2:  *                                  _   _ ____  _
                      3:  *  Project                     ___| | | |  _ \| |
                      4:  *                             / __| | | | |_) | |
                      5:  *                            | (__| |_| |  _ <| |___
                      6:  *                             \___|\___/|_| \_\_____|
                      7:  *
                      8:  * Copyright (C) 1998 - 2020, 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.haxx.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:  ***************************************************************************/
                     22: 
                     23: #include "curl_setup.h"
                     24: 
                     25: #include <curl/curl.h>
                     26: 
                     27: #include "urldata.h"
                     28: #include "getinfo.h"
                     29: 
                     30: #include "vtls/vtls.h"
                     31: #include "connect.h" /* Curl_getconnectinfo() */
                     32: #include "progress.h"
                     33: 
                     34: /* The last #include files should be: */
                     35: #include "curl_memory.h"
                     36: #include "memdebug.h"
                     37: 
                     38: /*
                     39:  * Initialize statistical and informational data.
                     40:  *
                     41:  * This function is called in curl_easy_reset, curl_easy_duphandle and at the
                     42:  * beginning of a perform session. It must reset the session-info variables,
                     43:  * in particular all variables in struct PureInfo.
                     44:  */
                     45: CURLcode Curl_initinfo(struct Curl_easy *data)
                     46: {
                     47:   struct Progress *pro = &data->progress;
                     48:   struct PureInfo *info = &data->info;
                     49: 
                     50:   pro->t_nslookup = 0;
                     51:   pro->t_connect = 0;
                     52:   pro->t_appconnect = 0;
                     53:   pro->t_pretransfer = 0;
                     54:   pro->t_starttransfer = 0;
                     55:   pro->timespent = 0;
                     56:   pro->t_redirect = 0;
                     57:   pro->is_t_startransfer_set = false;
                     58: 
                     59:   info->httpcode = 0;
                     60:   info->httpproxycode = 0;
                     61:   info->httpversion = 0;
                     62:   info->filetime = -1; /* -1 is an illegal time and thus means unknown */
                     63:   info->timecond = FALSE;
                     64: 
                     65:   info->header_size = 0;
                     66:   info->request_size = 0;
                     67:   info->proxyauthavail = 0;
                     68:   info->httpauthavail = 0;
                     69:   info->numconnects = 0;
                     70: 
                     71:   free(info->contenttype);
                     72:   info->contenttype = NULL;
                     73: 
                     74:   free(info->wouldredirect);
                     75:   info->wouldredirect = NULL;
                     76: 
                     77:   info->conn_primary_ip[0] = '\0';
                     78:   info->conn_local_ip[0] = '\0';
                     79:   info->conn_primary_port = 0;
                     80:   info->conn_local_port = 0;
                     81: 
                     82:   info->conn_scheme = 0;
                     83:   info->conn_protocol = 0;
                     84: 
                     85: #ifdef USE_SSL
                     86:   Curl_ssl_free_certinfo(data);
                     87: #endif
                     88:   return CURLE_OK;
                     89: }
                     90: 
                     91: static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info,
                     92:                              const char **param_charp)
                     93: {
                     94:   switch(info) {
                     95:   case CURLINFO_EFFECTIVE_URL:
                     96:     *param_charp = data->change.url?data->change.url:(char *)"";
                     97:     break;
                     98:   case CURLINFO_CONTENT_TYPE:
                     99:     *param_charp = data->info.contenttype;
                    100:     break;
                    101:   case CURLINFO_PRIVATE:
                    102:     *param_charp = (char *) data->set.private_data;
                    103:     break;
                    104:   case CURLINFO_FTP_ENTRY_PATH:
                    105:     /* Return the entrypath string from the most recent connection.
                    106:        This pointer was copied from the connectdata structure by FTP.
                    107:        The actual string may be free()ed by subsequent libcurl calls so
                    108:        it must be copied to a safer area before the next libcurl call.
                    109:        Callers must never free it themselves. */
                    110:     *param_charp = data->state.most_recent_ftp_entrypath;
                    111:     break;
                    112:   case CURLINFO_REDIRECT_URL:
                    113:     /* Return the URL this request would have been redirected to if that
                    114:        option had been enabled! */
                    115:     *param_charp = data->info.wouldredirect;
                    116:     break;
                    117:   case CURLINFO_PRIMARY_IP:
                    118:     /* Return the ip address of the most recent (primary) connection */
                    119:     *param_charp = data->info.conn_primary_ip;
                    120:     break;
                    121:   case CURLINFO_LOCAL_IP:
                    122:     /* Return the source/local ip address of the most recent (primary)
                    123:        connection */
                    124:     *param_charp = data->info.conn_local_ip;
                    125:     break;
                    126:   case CURLINFO_RTSP_SESSION_ID:
                    127:     *param_charp = data->set.str[STRING_RTSP_SESSION_ID];
                    128:     break;
                    129:   case CURLINFO_SCHEME:
                    130:     *param_charp = data->info.conn_scheme;
                    131:     break;
                    132: 
                    133:   default:
                    134:     return CURLE_UNKNOWN_OPTION;
                    135:   }
                    136: 
                    137:   return CURLE_OK;
                    138: }
                    139: 
                    140: static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
                    141:                              long *param_longp)
                    142: {
                    143:   curl_socket_t sockfd;
                    144: 
                    145:   union {
                    146:     unsigned long *to_ulong;
                    147:     long          *to_long;
                    148:   } lptr;
                    149: 
                    150: #ifdef DEBUGBUILD
                    151:   char *timestr = getenv("CURL_TIME");
                    152:   if(timestr) {
                    153:     unsigned long val = strtol(timestr, NULL, 10);
                    154:     switch(info) {
                    155:     case CURLINFO_LOCAL_PORT:
                    156:       *param_longp = (long)val;
                    157:       return CURLE_OK;
                    158:     default:
                    159:       break;
                    160:     }
                    161:   }
                    162:   /* use another variable for this to allow different values */
                    163:   timestr = getenv("CURL_DEBUG_SIZE");
                    164:   if(timestr) {
                    165:     unsigned long val = strtol(timestr, NULL, 10);
                    166:     switch(info) {
                    167:     case CURLINFO_HEADER_SIZE:
                    168:     case CURLINFO_REQUEST_SIZE:
                    169:       *param_longp = (long)val;
                    170:       return CURLE_OK;
                    171:     default:
                    172:       break;
                    173:     }
                    174:   }
                    175: #endif
                    176: 
                    177:   switch(info) {
                    178:   case CURLINFO_RESPONSE_CODE:
                    179:     *param_longp = data->info.httpcode;
                    180:     break;
                    181:   case CURLINFO_HTTP_CONNECTCODE:
                    182:     *param_longp = data->info.httpproxycode;
                    183:     break;
                    184:   case CURLINFO_FILETIME:
                    185:     if(data->info.filetime > LONG_MAX)
                    186:       *param_longp = LONG_MAX;
                    187:     else if(data->info.filetime < LONG_MIN)
                    188:       *param_longp = LONG_MIN;
                    189:     else
                    190:       *param_longp = (long)data->info.filetime;
                    191:     break;
                    192:   case CURLINFO_HEADER_SIZE:
                    193:     *param_longp = (long)data->info.header_size;
                    194:     break;
                    195:   case CURLINFO_REQUEST_SIZE:
                    196:     *param_longp = (long)data->info.request_size;
                    197:     break;
                    198:   case CURLINFO_SSL_VERIFYRESULT:
                    199:     *param_longp = data->set.ssl.certverifyresult;
                    200:     break;
                    201:   case CURLINFO_PROXY_SSL_VERIFYRESULT:
                    202:     *param_longp = data->set.proxy_ssl.certverifyresult;
                    203:     break;
                    204:   case CURLINFO_REDIRECT_COUNT:
                    205:     *param_longp = data->set.followlocation;
                    206:     break;
                    207:   case CURLINFO_HTTPAUTH_AVAIL:
                    208:     lptr.to_long = param_longp;
                    209:     *lptr.to_ulong = data->info.httpauthavail;
                    210:     break;
                    211:   case CURLINFO_PROXYAUTH_AVAIL:
                    212:     lptr.to_long = param_longp;
                    213:     *lptr.to_ulong = data->info.proxyauthavail;
                    214:     break;
                    215:   case CURLINFO_OS_ERRNO:
                    216:     *param_longp = data->state.os_errno;
                    217:     break;
                    218:   case CURLINFO_NUM_CONNECTS:
                    219:     *param_longp = data->info.numconnects;
                    220:     break;
                    221:   case CURLINFO_LASTSOCKET:
                    222:     sockfd = Curl_getconnectinfo(data, NULL);
                    223: 
                    224:     /* note: this is not a good conversion for systems with 64 bit sockets and
                    225:        32 bit longs */
                    226:     if(sockfd != CURL_SOCKET_BAD)
                    227:       *param_longp = (long)sockfd;
                    228:     else
                    229:       /* this interface is documented to return -1 in case of badness, which
                    230:          may not be the same as the CURL_SOCKET_BAD value */
                    231:       *param_longp = -1;
                    232:     break;
                    233:   case CURLINFO_PRIMARY_PORT:
                    234:     /* Return the (remote) port of the most recent (primary) connection */
                    235:     *param_longp = data->info.conn_primary_port;
                    236:     break;
                    237:   case CURLINFO_LOCAL_PORT:
                    238:     /* Return the local port of the most recent (primary) connection */
                    239:     *param_longp = data->info.conn_local_port;
                    240:     break;
                    241:   case CURLINFO_CONDITION_UNMET:
                    242:     if(data->info.httpcode == 304)
                    243:       *param_longp = 1L;
                    244:     else
                    245:       /* return if the condition prevented the document to get transferred */
                    246:       *param_longp = data->info.timecond ? 1L : 0L;
                    247:     break;
                    248:   case CURLINFO_RTSP_CLIENT_CSEQ:
                    249:     *param_longp = data->state.rtsp_next_client_CSeq;
                    250:     break;
                    251:   case CURLINFO_RTSP_SERVER_CSEQ:
                    252:     *param_longp = data->state.rtsp_next_server_CSeq;
                    253:     break;
                    254:   case CURLINFO_RTSP_CSEQ_RECV:
                    255:     *param_longp = data->state.rtsp_CSeq_recv;
                    256:     break;
                    257:   case CURLINFO_HTTP_VERSION:
                    258:     switch(data->info.httpversion) {
                    259:     case 10:
                    260:       *param_longp = CURL_HTTP_VERSION_1_0;
                    261:       break;
                    262:     case 11:
                    263:       *param_longp = CURL_HTTP_VERSION_1_1;
                    264:       break;
                    265:     case 20:
                    266:       *param_longp = CURL_HTTP_VERSION_2_0;
                    267:       break;
                    268:     case 30:
                    269:       *param_longp = CURL_HTTP_VERSION_3;
                    270:       break;
                    271:     default:
                    272:       *param_longp = CURL_HTTP_VERSION_NONE;
                    273:       break;
                    274:     }
                    275:     break;
                    276:   case CURLINFO_PROTOCOL:
                    277:     *param_longp = data->info.conn_protocol;
                    278:     break;
                    279:   default:
                    280:     return CURLE_UNKNOWN_OPTION;
                    281:   }
                    282: 
                    283:   return CURLE_OK;
                    284: }
                    285: 
                    286: #define DOUBLE_SECS(x) (double)(x)/1000000
                    287: 
                    288: static CURLcode getinfo_offt(struct Curl_easy *data, CURLINFO info,
                    289:                              curl_off_t *param_offt)
                    290: {
                    291: #ifdef DEBUGBUILD
                    292:   char *timestr = getenv("CURL_TIME");
                    293:   if(timestr) {
                    294:     unsigned long val = strtol(timestr, NULL, 10);
                    295:     switch(info) {
                    296:     case CURLINFO_TOTAL_TIME_T:
                    297:     case CURLINFO_NAMELOOKUP_TIME_T:
                    298:     case CURLINFO_CONNECT_TIME_T:
                    299:     case CURLINFO_APPCONNECT_TIME_T:
                    300:     case CURLINFO_PRETRANSFER_TIME_T:
                    301:     case CURLINFO_STARTTRANSFER_TIME_T:
                    302:     case CURLINFO_REDIRECT_TIME_T:
                    303:     case CURLINFO_SPEED_DOWNLOAD_T:
                    304:     case CURLINFO_SPEED_UPLOAD_T:
                    305:       *param_offt = (curl_off_t)val;
                    306:       return CURLE_OK;
                    307:     default:
                    308:       break;
                    309:     }
                    310:   }
                    311: #endif
                    312:   switch(info) {
                    313:   case CURLINFO_FILETIME_T:
                    314:     *param_offt = (curl_off_t)data->info.filetime;
                    315:     break;
                    316:   case CURLINFO_SIZE_UPLOAD_T:
                    317:     *param_offt = data->progress.uploaded;
                    318:     break;
                    319:   case CURLINFO_SIZE_DOWNLOAD_T:
                    320:     *param_offt = data->progress.downloaded;
                    321:     break;
                    322:   case CURLINFO_SPEED_DOWNLOAD_T:
                    323:     *param_offt =  data->progress.dlspeed;
                    324:     break;
                    325:   case CURLINFO_SPEED_UPLOAD_T:
                    326:     *param_offt = data->progress.ulspeed;
                    327:     break;
                    328:   case CURLINFO_CONTENT_LENGTH_DOWNLOAD_T:
                    329:     *param_offt = (data->progress.flags & PGRS_DL_SIZE_KNOWN)?
                    330:       data->progress.size_dl:-1;
                    331:     break;
                    332:   case CURLINFO_CONTENT_LENGTH_UPLOAD_T:
                    333:     *param_offt = (data->progress.flags & PGRS_UL_SIZE_KNOWN)?
                    334:       data->progress.size_ul:-1;
                    335:     break;
                    336:    case CURLINFO_TOTAL_TIME_T:
                    337:     *param_offt = data->progress.timespent;
                    338:     break;
                    339:   case CURLINFO_NAMELOOKUP_TIME_T:
                    340:     *param_offt = data->progress.t_nslookup;
                    341:     break;
                    342:   case CURLINFO_CONNECT_TIME_T:
                    343:     *param_offt = data->progress.t_connect;
                    344:     break;
                    345:   case CURLINFO_APPCONNECT_TIME_T:
                    346:     *param_offt = data->progress.t_appconnect;
                    347:     break;
                    348:   case CURLINFO_PRETRANSFER_TIME_T:
                    349:     *param_offt = data->progress.t_pretransfer;
                    350:     break;
                    351:   case CURLINFO_STARTTRANSFER_TIME_T:
                    352:     *param_offt = data->progress.t_starttransfer;
                    353:     break;
                    354:   case CURLINFO_REDIRECT_TIME_T:
                    355:     *param_offt = data->progress.t_redirect;
                    356:     break;
                    357:   case CURLINFO_RETRY_AFTER:
                    358:     *param_offt = data->info.retry_after;
                    359:     break;
                    360:   default:
                    361:     return CURLE_UNKNOWN_OPTION;
                    362:   }
                    363: 
                    364:   return CURLE_OK;
                    365: }
                    366: 
                    367: static CURLcode getinfo_double(struct Curl_easy *data, CURLINFO info,
                    368:                                double *param_doublep)
                    369: {
                    370: #ifdef DEBUGBUILD
                    371:   char *timestr = getenv("CURL_TIME");
                    372:   if(timestr) {
                    373:     unsigned long val = strtol(timestr, NULL, 10);
                    374:     switch(info) {
                    375:     case CURLINFO_TOTAL_TIME:
                    376:     case CURLINFO_NAMELOOKUP_TIME:
                    377:     case CURLINFO_CONNECT_TIME:
                    378:     case CURLINFO_APPCONNECT_TIME:
                    379:     case CURLINFO_PRETRANSFER_TIME:
                    380:     case CURLINFO_STARTTRANSFER_TIME:
                    381:     case CURLINFO_REDIRECT_TIME:
                    382:     case CURLINFO_SPEED_DOWNLOAD:
                    383:     case CURLINFO_SPEED_UPLOAD:
                    384:       *param_doublep = (double)val;
                    385:       return CURLE_OK;
                    386:     default:
                    387:       break;
                    388:     }
                    389:   }
                    390: #endif
                    391:   switch(info) {
                    392:   case CURLINFO_TOTAL_TIME:
                    393:     *param_doublep = DOUBLE_SECS(data->progress.timespent);
                    394:     break;
                    395:   case CURLINFO_NAMELOOKUP_TIME:
                    396:     *param_doublep = DOUBLE_SECS(data->progress.t_nslookup);
                    397:     break;
                    398:   case CURLINFO_CONNECT_TIME:
                    399:     *param_doublep = DOUBLE_SECS(data->progress.t_connect);
                    400:     break;
                    401:   case CURLINFO_APPCONNECT_TIME:
                    402:     *param_doublep = DOUBLE_SECS(data->progress.t_appconnect);
                    403:     break;
                    404:   case CURLINFO_PRETRANSFER_TIME:
                    405:     *param_doublep = DOUBLE_SECS(data->progress.t_pretransfer);
                    406:     break;
                    407:   case CURLINFO_STARTTRANSFER_TIME:
                    408:     *param_doublep = DOUBLE_SECS(data->progress.t_starttransfer);
                    409:     break;
                    410:   case CURLINFO_SIZE_UPLOAD:
                    411:     *param_doublep =  (double)data->progress.uploaded;
                    412:     break;
                    413:   case CURLINFO_SIZE_DOWNLOAD:
                    414:     *param_doublep = (double)data->progress.downloaded;
                    415:     break;
                    416:   case CURLINFO_SPEED_DOWNLOAD:
                    417:     *param_doublep =  (double)data->progress.dlspeed;
                    418:     break;
                    419:   case CURLINFO_SPEED_UPLOAD:
                    420:     *param_doublep = (double)data->progress.ulspeed;
                    421:     break;
                    422:   case CURLINFO_CONTENT_LENGTH_DOWNLOAD:
                    423:     *param_doublep = (data->progress.flags & PGRS_DL_SIZE_KNOWN)?
                    424:       (double)data->progress.size_dl:-1;
                    425:     break;
                    426:   case CURLINFO_CONTENT_LENGTH_UPLOAD:
                    427:     *param_doublep = (data->progress.flags & PGRS_UL_SIZE_KNOWN)?
                    428:       (double)data->progress.size_ul:-1;
                    429:     break;
                    430:   case CURLINFO_REDIRECT_TIME:
                    431:     *param_doublep = DOUBLE_SECS(data->progress.t_redirect);
                    432:     break;
                    433: 
                    434:   default:
                    435:     return CURLE_UNKNOWN_OPTION;
                    436:   }
                    437: 
                    438:   return CURLE_OK;
                    439: }
                    440: 
                    441: static CURLcode getinfo_slist(struct Curl_easy *data, CURLINFO info,
                    442:                               struct curl_slist **param_slistp)
                    443: {
                    444:   union {
                    445:     struct curl_certinfo *to_certinfo;
                    446:     struct curl_slist    *to_slist;
                    447:   } ptr;
                    448: 
                    449:   switch(info) {
                    450:   case CURLINFO_SSL_ENGINES:
                    451:     *param_slistp = Curl_ssl_engines_list(data);
                    452:     break;
                    453:   case CURLINFO_COOKIELIST:
                    454:     *param_slistp = Curl_cookie_list(data);
                    455:     break;
                    456:   case CURLINFO_CERTINFO:
                    457:     /* Return the a pointer to the certinfo struct. Not really an slist
                    458:        pointer but we can pretend it is here */
                    459:     ptr.to_certinfo = &data->info.certs;
                    460:     *param_slistp = ptr.to_slist;
                    461:     break;
                    462:   case CURLINFO_TLS_SESSION:
                    463:   case CURLINFO_TLS_SSL_PTR:
                    464:     {
                    465:       struct curl_tlssessioninfo **tsip = (struct curl_tlssessioninfo **)
                    466:                                           param_slistp;
                    467:       struct curl_tlssessioninfo *tsi = &data->tsi;
                    468: #ifdef USE_SSL
                    469:       struct connectdata *conn = data->conn;
                    470: #endif
                    471: 
                    472:       *tsip = tsi;
                    473:       tsi->backend = Curl_ssl_backend();
                    474:       tsi->internals = NULL;
                    475: 
                    476: #ifdef USE_SSL
                    477:       if(conn && tsi->backend != CURLSSLBACKEND_NONE) {
                    478:         unsigned int i;
                    479:         for(i = 0; i < (sizeof(conn->ssl) / sizeof(conn->ssl[0])); ++i) {
                    480:           if(conn->ssl[i].use) {
                    481:             tsi->internals = Curl_ssl->get_internals(&conn->ssl[i], info);
                    482:             break;
                    483:           }
                    484:         }
                    485:       }
                    486: #endif
                    487:     }
                    488:     break;
                    489:   default:
                    490:     return CURLE_UNKNOWN_OPTION;
                    491:   }
                    492: 
                    493:   return CURLE_OK;
                    494: }
                    495: 
                    496: static CURLcode getinfo_socket(struct Curl_easy *data, CURLINFO info,
                    497:                                curl_socket_t *param_socketp)
                    498: {
                    499:   switch(info) {
                    500:   case CURLINFO_ACTIVESOCKET:
                    501:     *param_socketp = Curl_getconnectinfo(data, NULL);
                    502:     break;
                    503:   default:
                    504:     return CURLE_UNKNOWN_OPTION;
                    505:   }
                    506: 
                    507:   return CURLE_OK;
                    508: }
                    509: 
                    510: CURLcode Curl_getinfo(struct Curl_easy *data, CURLINFO info, ...)
                    511: {
                    512:   va_list arg;
                    513:   long *param_longp = NULL;
                    514:   double *param_doublep = NULL;
                    515:   curl_off_t *param_offt = NULL;
                    516:   const char **param_charp = NULL;
                    517:   struct curl_slist **param_slistp = NULL;
                    518:   curl_socket_t *param_socketp = NULL;
                    519:   int type;
                    520:   CURLcode result = CURLE_UNKNOWN_OPTION;
                    521: 
                    522:   if(!data)
                    523:     return result;
                    524: 
                    525:   va_start(arg, info);
                    526: 
                    527:   type = CURLINFO_TYPEMASK & (int)info;
                    528:   switch(type) {
                    529:   case CURLINFO_STRING:
                    530:     param_charp = va_arg(arg, const char **);
                    531:     if(param_charp)
                    532:       result = getinfo_char(data, info, param_charp);
                    533:     break;
                    534:   case CURLINFO_LONG:
                    535:     param_longp = va_arg(arg, long *);
                    536:     if(param_longp)
                    537:       result = getinfo_long(data, info, param_longp);
                    538:     break;
                    539:   case CURLINFO_DOUBLE:
                    540:     param_doublep = va_arg(arg, double *);
                    541:     if(param_doublep)
                    542:       result = getinfo_double(data, info, param_doublep);
                    543:     break;
                    544:   case CURLINFO_OFF_T:
                    545:     param_offt = va_arg(arg, curl_off_t *);
                    546:     if(param_offt)
                    547:       result = getinfo_offt(data, info, param_offt);
                    548:     break;
                    549:   case CURLINFO_SLIST:
                    550:     param_slistp = va_arg(arg, struct curl_slist **);
                    551:     if(param_slistp)
                    552:       result = getinfo_slist(data, info, param_slistp);
                    553:     break;
                    554:   case CURLINFO_SOCKET:
                    555:     param_socketp = va_arg(arg, curl_socket_t *);
                    556:     if(param_socketp)
                    557:       result = getinfo_socket(data, info, param_socketp);
                    558:     break;
                    559:   default:
                    560:     break;
                    561:   }
                    562: 
                    563:   va_end(arg);
                    564: 
                    565:   return result;
                    566: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>