1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2017, 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 *param_longp = data->info.filetime;
161 case CURLINFO_HEADER_SIZE:
162 *param_longp = data->info.header_size;
164 case CURLINFO_REQUEST_SIZE:
165 *param_longp = data->info.request_size;
167 case CURLINFO_SSL_VERIFYRESULT:
168 *param_longp = data->set.ssl.certverifyresult;
170 case CURLINFO_PROXY_SSL_VERIFYRESULT:
171 *param_longp = data->set.proxy_ssl.certverifyresult;
173 case CURLINFO_REDIRECT_COUNT:
174 *param_longp = data->set.followlocation;
176 case CURLINFO_HTTPAUTH_AVAIL:
177 lptr.to_long = param_longp;
178 *lptr.to_ulong = data->info.httpauthavail;
180 case CURLINFO_PROXYAUTH_AVAIL:
181 lptr.to_long = param_longp;
182 *lptr.to_ulong = data->info.proxyauthavail;
184 case CURLINFO_OS_ERRNO:
185 *param_longp = data->state.os_errno;
187 case CURLINFO_NUM_CONNECTS:
188 *param_longp = data->info.numconnects;
190 case CURLINFO_LASTSOCKET:
191 sockfd = Curl_getconnectinfo(data, NULL);
193 /* note: this is not a good conversion for systems with 64 bit sockets and
195 if(sockfd != CURL_SOCKET_BAD)
196 *param_longp = (long)sockfd;
198 /* this interface is documented to return -1 in case of badness, which
199 may not be the same as the CURL_SOCKET_BAD value */
202 case CURLINFO_PRIMARY_PORT:
203 /* Return the (remote) port of the most recent (primary) connection */
204 *param_longp = data->info.conn_primary_port;
206 case CURLINFO_LOCAL_PORT:
207 /* Return the local port of the most recent (primary) connection */
208 *param_longp = data->info.conn_local_port;
210 case CURLINFO_CONDITION_UNMET:
211 /* return if the condition prevented the document to get transferred */
212 *param_longp = data->info.timecond ? 1L : 0L;
214 case CURLINFO_RTSP_CLIENT_CSEQ:
215 *param_longp = data->state.rtsp_next_client_CSeq;
217 case CURLINFO_RTSP_SERVER_CSEQ:
218 *param_longp = data->state.rtsp_next_server_CSeq;
220 case CURLINFO_RTSP_CSEQ_RECV:
221 *param_longp = data->state.rtsp_CSeq_recv;
223 case CURLINFO_HTTP_VERSION:
224 switch(data->info.httpversion) {
226 *param_longp = CURL_HTTP_VERSION_1_0;
229 *param_longp = CURL_HTTP_VERSION_1_1;
232 *param_longp = CURL_HTTP_VERSION_2_0;
235 *param_longp = CURL_HTTP_VERSION_NONE;
239 case CURLINFO_PROTOCOL:
240 *param_longp = data->info.conn_protocol;
244 return CURLE_UNKNOWN_OPTION;
250 #define DOUBLE_SECS(x) (double)(x)/1000000
252 static CURLcode getinfo_offt(struct Curl_easy *data, CURLINFO info,
253 curl_off_t *param_offt)
256 case CURLINFO_SIZE_UPLOAD_T:
257 *param_offt = data->progress.uploaded;
259 case CURLINFO_SIZE_DOWNLOAD_T:
260 *param_offt = data->progress.downloaded;
262 case CURLINFO_SPEED_DOWNLOAD_T:
263 *param_offt = data->progress.dlspeed;
265 case CURLINFO_SPEED_UPLOAD_T:
266 *param_offt = data->progress.ulspeed;
268 case CURLINFO_CONTENT_LENGTH_DOWNLOAD_T:
269 *param_offt = (data->progress.flags & PGRS_DL_SIZE_KNOWN)?
270 data->progress.size_dl:-1;
272 case CURLINFO_CONTENT_LENGTH_UPLOAD_T:
273 *param_offt = (data->progress.flags & PGRS_UL_SIZE_KNOWN)?
274 data->progress.size_ul:-1;
277 return CURLE_UNKNOWN_OPTION;
283 static CURLcode getinfo_double(struct Curl_easy *data, CURLINFO info,
284 double *param_doublep)
287 case CURLINFO_TOTAL_TIME:
288 *param_doublep = DOUBLE_SECS(data->progress.timespent);
290 case CURLINFO_NAMELOOKUP_TIME:
291 *param_doublep = DOUBLE_SECS(data->progress.t_nslookup);
293 case CURLINFO_CONNECT_TIME:
294 *param_doublep = DOUBLE_SECS(data->progress.t_connect);
296 case CURLINFO_APPCONNECT_TIME:
297 *param_doublep = DOUBLE_SECS(data->progress.t_appconnect);
299 case CURLINFO_PRETRANSFER_TIME:
300 *param_doublep = DOUBLE_SECS(data->progress.t_pretransfer);
302 case CURLINFO_STARTTRANSFER_TIME:
303 *param_doublep = DOUBLE_SECS(data->progress.t_starttransfer);
305 case CURLINFO_SIZE_UPLOAD:
306 *param_doublep = (double)data->progress.uploaded;
308 case CURLINFO_SIZE_DOWNLOAD:
309 *param_doublep = (double)data->progress.downloaded;
311 case CURLINFO_SPEED_DOWNLOAD:
312 *param_doublep = (double)data->progress.dlspeed;
314 case CURLINFO_SPEED_UPLOAD:
315 *param_doublep = (double)data->progress.ulspeed;
317 case CURLINFO_CONTENT_LENGTH_DOWNLOAD:
318 *param_doublep = (data->progress.flags & PGRS_DL_SIZE_KNOWN)?
319 (double)data->progress.size_dl:-1;
321 case CURLINFO_CONTENT_LENGTH_UPLOAD:
322 *param_doublep = (data->progress.flags & PGRS_UL_SIZE_KNOWN)?
323 (double)data->progress.size_ul:-1;
325 case CURLINFO_REDIRECT_TIME:
326 *param_doublep = DOUBLE_SECS(data->progress.t_redirect);
330 return CURLE_UNKNOWN_OPTION;
336 static CURLcode getinfo_slist(struct Curl_easy *data, CURLINFO info,
337 struct curl_slist **param_slistp)
340 struct curl_certinfo *to_certinfo;
341 struct curl_slist *to_slist;
345 case CURLINFO_SSL_ENGINES:
346 *param_slistp = Curl_ssl_engines_list(data);
348 case CURLINFO_COOKIELIST:
349 *param_slistp = Curl_cookie_list(data);
351 case CURLINFO_CERTINFO:
352 /* Return the a pointer to the certinfo struct. Not really an slist
353 pointer but we can pretend it is here */
354 ptr.to_certinfo = &data->info.certs;
355 *param_slistp = ptr.to_slist;
357 case CURLINFO_TLS_SESSION:
358 case CURLINFO_TLS_SSL_PTR:
360 struct curl_tlssessioninfo **tsip = (struct curl_tlssessioninfo **)
362 struct curl_tlssessioninfo *tsi = &data->tsi;
364 struct connectdata *conn = data->easy_conn;
368 tsi->backend = Curl_ssl_backend();
369 tsi->internals = NULL;
372 if(conn && tsi->backend != CURLSSLBACKEND_NONE) {
374 for(i = 0; i < (sizeof(conn->ssl) / sizeof(conn->ssl[0])); ++i) {
375 if(conn->ssl[i].use) {
376 tsi->internals = Curl_ssl->get_internals(&conn->ssl[i], info);
385 return CURLE_UNKNOWN_OPTION;
391 static CURLcode getinfo_socket(struct Curl_easy *data, CURLINFO info,
392 curl_socket_t *param_socketp)
395 case CURLINFO_ACTIVESOCKET:
396 *param_socketp = Curl_getconnectinfo(data, NULL);
399 return CURLE_UNKNOWN_OPTION;
405 CURLcode Curl_getinfo(struct Curl_easy *data, CURLINFO info, ...)
408 long *param_longp = NULL;
409 double *param_doublep = NULL;
410 curl_off_t *param_offt = NULL;
411 const char **param_charp = NULL;
412 struct curl_slist **param_slistp = NULL;
413 curl_socket_t *param_socketp = NULL;
415 CURLcode result = CURLE_UNKNOWN_OPTION;
422 type = CURLINFO_TYPEMASK & (int)info;
424 case CURLINFO_STRING:
425 param_charp = va_arg(arg, const char **);
427 result = getinfo_char(data, info, param_charp);
430 param_longp = va_arg(arg, long *);
432 result = getinfo_long(data, info, param_longp);
434 case CURLINFO_DOUBLE:
435 param_doublep = va_arg(arg, double *);
437 result = getinfo_double(data, info, param_doublep);
440 param_offt = va_arg(arg, curl_off_t *);
442 result = getinfo_offt(data, info, param_offt);
445 param_slistp = va_arg(arg, struct curl_slist **);
447 result = getinfo_slist(data, info, param_slistp);
449 case CURLINFO_SOCKET:
450 param_socketp = va_arg(arg, curl_socket_t *);
452 result = getinfo_socket(data, info, param_socketp);