Coverage Report

Created: 2026-10-15 06:25

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