1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
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.
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.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ***************************************************************************/
23 #include "curl_setup.h"
25 #include <curl/curl.h>
30 #include "vtls/vtls.h"
31 #include "connect.h" /* Curl_getconnectinfo() */
34 /* The last #include files should be: */
35 #include "curl_memory.h"
39 * Initialize statistical and informational data.
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.
45 CURLcode Curl_initinfo(struct Curl_easy *data)
47 struct Progress *pro = &data->progress;
48 struct PureInfo *info = &data->info;
52 pro->t_appconnect = 0;
53 pro->t_pretransfer = 0;
54 pro->t_starttransfer = 0;
57 pro->is_t_startransfer_set = false;
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;
65 info->header_size = 0;
66 info->request_size = 0;
67 info->proxyauthavail = 0;
68 info->httpauthavail = 0;
69 info->numconnects = 0;
71 free(info->contenttype);
72 info->contenttype = NULL;
74 free(info->wouldredirect);
75 info->wouldredirect = NULL;
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;
82 info->conn_scheme = 0;
83 info->conn_protocol = 0;
86 Curl_ssl_free_certinfo(data);
92 static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info,
93 const char **param_charp)
96 case CURLINFO_EFFECTIVE_URL:
97 *param_charp = data->change.url?data->change.url:(char *)"";
99 case CURLINFO_CONTENT_TYPE:
100 *param_charp = data->info.contenttype;
102 case CURLINFO_PRIVATE:
103 *param_charp = (char *) data->set.private_data;
105 case CURLINFO_FTP_ENTRY_PATH:
106 /* Return the entrypath string from the most recent connection.
107 This pointer was copied from the connectdata structure by FTP.
108 The actual string may be free()ed by subsequent libcurl calls so
109 it must be copied to a safer area before the next libcurl call.
110 Callers must never free it themselves. */
111 *param_charp = data->state.most_recent_ftp_entrypath;
113 case CURLINFO_REDIRECT_URL:
114 /* Return the URL this request would have been redirected to if that
115 option had been enabled! */
116 *param_charp = data->info.wouldredirect;
118 case CURLINFO_PRIMARY_IP:
119 /* Return the ip address of the most recent (primary) connection */
120 *param_charp = data->info.conn_primary_ip;
122 case CURLINFO_LOCAL_IP:
123 /* Return the source/local ip address of the most recent (primary)
125 *param_charp = data->info.conn_local_ip;
127 case CURLINFO_RTSP_SESSION_ID:
128 *param_charp = data->set.str[STRING_RTSP_SESSION_ID];
130 case CURLINFO_SCHEME:
131 *param_charp = data->info.conn_scheme;
135 return CURLE_UNKNOWN_OPTION;
141 static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
144 curl_socket_t sockfd;
147 unsigned long *to_ulong;
152 case CURLINFO_RESPONSE_CODE:
153 *param_longp = data->info.httpcode;
155 case CURLINFO_HTTP_CONNECTCODE:
156 *param_longp = data->info.httpproxycode;
158 case CURLINFO_FILETIME:
159 if(data->info.filetime > LONG_MAX)
160 *param_longp = LONG_MAX;
161 else if(data->info.filetime < LONG_MIN)
162 *param_longp = LONG_MIN;
164 *param_longp = (long)data->info.filetime;
166 case CURLINFO_HEADER_SIZE:
167 *param_longp = data->info.header_size;
169 case CURLINFO_REQUEST_SIZE:
170 *param_longp = data->info.request_size;
172 case CURLINFO_SSL_VERIFYRESULT:
173 *param_longp = data->set.ssl.certverifyresult;
175 case CURLINFO_PROXY_SSL_VERIFYRESULT:
176 *param_longp = data->set.proxy_ssl.certverifyresult;
178 case CURLINFO_REDIRECT_COUNT:
179 *param_longp = data->set.followlocation;
181 case CURLINFO_HTTPAUTH_AVAIL:
182 lptr.to_long = param_longp;
183 *lptr.to_ulong = data->info.httpauthavail;
185 case CURLINFO_PROXYAUTH_AVAIL:
186 lptr.to_long = param_longp;
187 *lptr.to_ulong = data->info.proxyauthavail;
189 case CURLINFO_OS_ERRNO:
190 *param_longp = data->state.os_errno;
192 case CURLINFO_NUM_CONNECTS:
193 *param_longp = data->info.numconnects;
195 case CURLINFO_LASTSOCKET:
196 sockfd = Curl_getconnectinfo(data, NULL);
198 /* note: this is not a good conversion for systems with 64 bit sockets and
200 if(sockfd != CURL_SOCKET_BAD)
201 *param_longp = (long)sockfd;
203 /* this interface is documented to return -1 in case of badness, which
204 may not be the same as the CURL_SOCKET_BAD value */
207 case CURLINFO_PRIMARY_PORT:
208 /* Return the (remote) port of the most recent (primary) connection */
209 *param_longp = data->info.conn_primary_port;
211 case CURLINFO_LOCAL_PORT:
212 /* Return the local port of the most recent (primary) connection */
213 *param_longp = data->info.conn_local_port;
215 case CURLINFO_CONDITION_UNMET:
216 /* return if the condition prevented the document to get transferred */
217 *param_longp = data->info.timecond ? 1L : 0L;
219 case CURLINFO_RTSP_CLIENT_CSEQ:
220 *param_longp = data->state.rtsp_next_client_CSeq;
222 case CURLINFO_RTSP_SERVER_CSEQ:
223 *param_longp = data->state.rtsp_next_server_CSeq;
225 case CURLINFO_RTSP_CSEQ_RECV:
226 *param_longp = data->state.rtsp_CSeq_recv;
228 case CURLINFO_HTTP_VERSION:
229 switch(data->info.httpversion) {
231 *param_longp = CURL_HTTP_VERSION_1_0;
234 *param_longp = CURL_HTTP_VERSION_1_1;
237 *param_longp = CURL_HTTP_VERSION_2_0;
240 *param_longp = CURL_HTTP_VERSION_NONE;
244 case CURLINFO_PROTOCOL:
245 *param_longp = data->info.conn_protocol;
249 return CURLE_UNKNOWN_OPTION;
255 #define DOUBLE_SECS(x) (double)(x)/1000000
257 static CURLcode getinfo_offt(struct Curl_easy *data, CURLINFO info,
258 curl_off_t *param_offt)
261 case CURLINFO_FILETIME_T:
262 *param_offt = (curl_off_t)data->info.filetime;
264 case CURLINFO_SIZE_UPLOAD_T:
265 *param_offt = data->progress.uploaded;
267 case CURLINFO_SIZE_DOWNLOAD_T:
268 *param_offt = data->progress.downloaded;
270 case CURLINFO_SPEED_DOWNLOAD_T:
271 *param_offt = data->progress.dlspeed;
273 case CURLINFO_SPEED_UPLOAD_T:
274 *param_offt = data->progress.ulspeed;
276 case CURLINFO_CONTENT_LENGTH_DOWNLOAD_T:
277 *param_offt = (data->progress.flags & PGRS_DL_SIZE_KNOWN)?
278 data->progress.size_dl:-1;
280 case CURLINFO_CONTENT_LENGTH_UPLOAD_T:
281 *param_offt = (data->progress.flags & PGRS_UL_SIZE_KNOWN)?
282 data->progress.size_ul:-1;
285 return CURLE_UNKNOWN_OPTION;
291 static CURLcode getinfo_double(struct Curl_easy *data, CURLINFO info,
292 double *param_doublep)
295 case CURLINFO_TOTAL_TIME:
296 *param_doublep = DOUBLE_SECS(data->progress.timespent);
298 case CURLINFO_NAMELOOKUP_TIME:
299 *param_doublep = DOUBLE_SECS(data->progress.t_nslookup);
301 case CURLINFO_CONNECT_TIME:
302 *param_doublep = DOUBLE_SECS(data->progress.t_connect);
304 case CURLINFO_APPCONNECT_TIME:
305 *param_doublep = DOUBLE_SECS(data->progress.t_appconnect);
307 case CURLINFO_PRETRANSFER_TIME:
308 *param_doublep = DOUBLE_SECS(data->progress.t_pretransfer);
310 case CURLINFO_STARTTRANSFER_TIME:
311 *param_doublep = DOUBLE_SECS(data->progress.t_starttransfer);
313 case CURLINFO_SIZE_UPLOAD:
314 *param_doublep = (double)data->progress.uploaded;
316 case CURLINFO_SIZE_DOWNLOAD:
317 *param_doublep = (double)data->progress.downloaded;
319 case CURLINFO_SPEED_DOWNLOAD:
320 *param_doublep = (double)data->progress.dlspeed;
322 case CURLINFO_SPEED_UPLOAD:
323 *param_doublep = (double)data->progress.ulspeed;
325 case CURLINFO_CONTENT_LENGTH_DOWNLOAD:
326 *param_doublep = (data->progress.flags & PGRS_DL_SIZE_KNOWN)?
327 (double)data->progress.size_dl:-1;
329 case CURLINFO_CONTENT_LENGTH_UPLOAD:
330 *param_doublep = (data->progress.flags & PGRS_UL_SIZE_KNOWN)?
331 (double)data->progress.size_ul:-1;
333 case CURLINFO_REDIRECT_TIME:
334 *param_doublep = DOUBLE_SECS(data->progress.t_redirect);
338 return CURLE_UNKNOWN_OPTION;
344 static CURLcode getinfo_slist(struct Curl_easy *data, CURLINFO info,
345 struct curl_slist **param_slistp)
348 struct curl_certinfo *to_certinfo;
349 struct curl_slist *to_slist;
353 case CURLINFO_SSL_ENGINES:
354 *param_slistp = Curl_ssl_engines_list(data);
356 case CURLINFO_COOKIELIST:
357 *param_slistp = Curl_cookie_list(data);
359 case CURLINFO_CERTINFO:
360 /* Return the a pointer to the certinfo struct. Not really an slist
361 pointer but we can pretend it is here */
362 ptr.to_certinfo = &data->info.certs;
363 *param_slistp = ptr.to_slist;
365 case CURLINFO_TLS_SESSION:
366 case CURLINFO_TLS_SSL_PTR:
368 struct curl_tlssessioninfo **tsip = (struct curl_tlssessioninfo **)
370 struct curl_tlssessioninfo *tsi = &data->tsi;
372 struct connectdata *conn = data->easy_conn;
376 tsi->backend = Curl_ssl_backend();
377 tsi->internals = NULL;
380 if(conn && tsi->backend != CURLSSLBACKEND_NONE) {
382 for(i = 0; i < (sizeof(conn->ssl) / sizeof(conn->ssl[0])); ++i) {
383 if(conn->ssl[i].use) {
384 tsi->internals = Curl_ssl->get_internals(&conn->ssl[i], info);
393 return CURLE_UNKNOWN_OPTION;
399 static CURLcode getinfo_socket(struct Curl_easy *data, CURLINFO info,
400 curl_socket_t *param_socketp)
403 case CURLINFO_ACTIVESOCKET:
404 *param_socketp = Curl_getconnectinfo(data, NULL);
407 return CURLE_UNKNOWN_OPTION;
413 CURLcode Curl_getinfo(struct Curl_easy *data, CURLINFO info, ...)
416 long *param_longp = NULL;
417 double *param_doublep = NULL;
418 curl_off_t *param_offt = NULL;
419 const char **param_charp = NULL;
420 struct curl_slist **param_slistp = NULL;
421 curl_socket_t *param_socketp = NULL;
423 CURLcode result = CURLE_UNKNOWN_OPTION;
430 type = CURLINFO_TYPEMASK & (int)info;
432 case CURLINFO_STRING:
433 param_charp = va_arg(arg, const char **);
435 result = getinfo_char(data, info, param_charp);
438 param_longp = va_arg(arg, long *);
440 result = getinfo_long(data, info, param_longp);
442 case CURLINFO_DOUBLE:
443 param_doublep = va_arg(arg, double *);
445 result = getinfo_double(data, info, param_doublep);
448 param_offt = va_arg(arg, curl_off_t *);
450 result = getinfo_offt(data, info, param_offt);
453 param_slistp = va_arg(arg, struct curl_slist **);
455 result = getinfo_slist(data, info, param_slistp);
457 case CURLINFO_SOCKET:
458 param_socketp = va_arg(arg, curl_socket_t *);
460 result = getinfo_socket(data, info, param_socketp);