VirtualBox

source: vbox/trunk/src/libs/curl-8.7.1/lib/getinfo.c@ 106542

最後變更 在這個檔案從106542是 104083,由 vboxsync 提交於 11 月 前

curl-8.7.1: Applied and adjusted our curl changes to 8.4.0. bugref:10639

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette