Annotation of embedaddon/curl/lib/getinfo.c, revision 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>