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>