1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2016, 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;
59 info->httpproxycode = 0;
60 info->httpversion = 0;
61 info->filetime = -1; /* -1 is an illegal time and thus means unknown */
62 info->timecond = FALSE;
64 info->header_size = 0;
65 info->request_size = 0;
66 info->proxyauthavail = 0;
67 info->httpauthavail = 0;
68 info->numconnects = 0;
70 free(info->contenttype);
71 info->contenttype = NULL;
73 free(info->wouldredirect);
74 info->wouldredirect = NULL;
76 info->conn_primary_ip[0] = '\0';
77 info->conn_local_ip[0] = '\0';
78 info->conn_primary_port = 0;
79 info->conn_local_port = 0;
81 info->conn_scheme = 0;
82 info->conn_protocol = 0;
85 Curl_ssl_free_certinfo(data);
91 static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info,
92 const char **param_charp)
95 case CURLINFO_EFFECTIVE_URL:
96 *param_charp = data->change.url?data->change.url:(char *)"";
98 case CURLINFO_CONTENT_TYPE:
99 *param_charp = data->info.contenttype;
101 case CURLINFO_PRIVATE:
102 *param_charp = (char *) data->set.private_data;
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;
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;
117 case CURLINFO_PRIMARY_IP:
118 /* Return the ip address of the most recent (primary) connection */
119 *param_charp = data->info.conn_primary_ip;
121 case CURLINFO_LOCAL_IP:
122 /* Return the source/local ip address of the most recent (primary)
124 *param_charp = data->info.conn_local_ip;
126 case CURLINFO_RTSP_SESSION_ID:
127 *param_charp = data->set.str[STRING_RTSP_SESSION_ID];
129 case CURLINFO_SCHEME:
130 *param_charp = data->info.conn_scheme;
134 return CURLE_UNKNOWN_OPTION;
140 static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
143 curl_socket_t sockfd;
146 unsigned long *to_ulong;
151 case CURLINFO_RESPONSE_CODE:
152 *param_longp = data->info.httpcode;
154 case CURLINFO_HTTP_CONNECTCODE:
155 *param_longp = data->info.httpproxycode;
157 case CURLINFO_FILETIME:
158 *param_longp = data->info.filetime;
160 case CURLINFO_HEADER_SIZE:
161 *param_longp = data->info.header_size;
163 case CURLINFO_REQUEST_SIZE:
164 *param_longp = data->info.request_size;
166 case CURLINFO_SSL_VERIFYRESULT:
167 *param_longp = data->set.ssl.certverifyresult;
169 case CURLINFO_PROXY_SSL_VERIFYRESULT:
170 *param_longp = data->set.proxy_ssl.certverifyresult;
172 case CURLINFO_REDIRECT_COUNT:
173 *param_longp = data->set.followlocation;
175 case CURLINFO_HTTPAUTH_AVAIL:
176 lptr.to_long = param_longp;
177 *lptr.to_ulong = data->info.httpauthavail;
179 case CURLINFO_PROXYAUTH_AVAIL:
180 lptr.to_long = param_longp;
181 *lptr.to_ulong = data->info.proxyauthavail;
183 case CURLINFO_OS_ERRNO:
184 *param_longp = data->state.os_errno;
186 case CURLINFO_NUM_CONNECTS:
187 *param_longp = data->info.numconnects;
189 case CURLINFO_LASTSOCKET:
190 sockfd = Curl_getconnectinfo(data, NULL);
192 /* note: this is not a good conversion for systems with 64 bit sockets and
194 if(sockfd != CURL_SOCKET_BAD)
195 *param_longp = (long)sockfd;
197 /* this interface is documented to return -1 in case of badness, which
198 may not be the same as the CURL_SOCKET_BAD value */
201 case CURLINFO_PRIMARY_PORT:
202 /* Return the (remote) port of the most recent (primary) connection */
203 *param_longp = data->info.conn_primary_port;
205 case CURLINFO_LOCAL_PORT:
206 /* Return the local port of the most recent (primary) connection */
207 *param_longp = data->info.conn_local_port;
209 case CURLINFO_CONDITION_UNMET:
210 /* return if the condition prevented the document to get transferred */
211 *param_longp = data->info.timecond ? 1L : 0L;
213 case CURLINFO_RTSP_CLIENT_CSEQ:
214 *param_longp = data->state.rtsp_next_client_CSeq;
216 case CURLINFO_RTSP_SERVER_CSEQ:
217 *param_longp = data->state.rtsp_next_server_CSeq;
219 case CURLINFO_RTSP_CSEQ_RECV:
220 *param_longp = data->state.rtsp_CSeq_recv;
222 case CURLINFO_HTTP_VERSION:
223 switch(data->info.httpversion) {
225 *param_longp = CURL_HTTP_VERSION_1_0;
228 *param_longp = CURL_HTTP_VERSION_1_1;
231 *param_longp = CURL_HTTP_VERSION_2_0;
234 *param_longp = CURL_HTTP_VERSION_NONE;
238 case CURLINFO_PROTOCOL:
239 *param_longp = data->info.conn_protocol;
243 return CURLE_UNKNOWN_OPTION;
249 static CURLcode getinfo_double(struct Curl_easy *data, CURLINFO info,
250 double *param_doublep)
253 case CURLINFO_TOTAL_TIME:
254 *param_doublep = data->progress.timespent;
256 case CURLINFO_NAMELOOKUP_TIME:
257 *param_doublep = data->progress.t_nslookup;
259 case CURLINFO_CONNECT_TIME:
260 *param_doublep = data->progress.t_connect;
262 case CURLINFO_APPCONNECT_TIME:
263 *param_doublep = data->progress.t_appconnect;
265 case CURLINFO_PRETRANSFER_TIME:
266 *param_doublep = data->progress.t_pretransfer;
268 case CURLINFO_STARTTRANSFER_TIME:
269 *param_doublep = data->progress.t_starttransfer;
271 case CURLINFO_SIZE_UPLOAD:
272 *param_doublep = (double)data->progress.uploaded;
274 case CURLINFO_SIZE_DOWNLOAD:
275 *param_doublep = (double)data->progress.downloaded;
277 case CURLINFO_SPEED_DOWNLOAD:
278 *param_doublep = (double)data->progress.dlspeed;
280 case CURLINFO_SPEED_UPLOAD:
281 *param_doublep = (double)data->progress.ulspeed;
283 case CURLINFO_CONTENT_LENGTH_DOWNLOAD:
284 *param_doublep = (data->progress.flags & PGRS_DL_SIZE_KNOWN)?
285 (double)data->progress.size_dl:-1;
287 case CURLINFO_CONTENT_LENGTH_UPLOAD:
288 *param_doublep = (data->progress.flags & PGRS_UL_SIZE_KNOWN)?
289 (double)data->progress.size_ul:-1;
291 case CURLINFO_REDIRECT_TIME:
292 *param_doublep = data->progress.t_redirect;
296 return CURLE_UNKNOWN_OPTION;
302 static CURLcode getinfo_slist(struct Curl_easy *data, CURLINFO info,
303 struct curl_slist **param_slistp)
306 struct curl_certinfo *to_certinfo;
307 struct curl_slist *to_slist;
311 case CURLINFO_SSL_ENGINES:
312 *param_slistp = Curl_ssl_engines_list(data);
314 case CURLINFO_COOKIELIST:
315 *param_slistp = Curl_cookie_list(data);
317 case CURLINFO_CERTINFO:
318 /* Return the a pointer to the certinfo struct. Not really an slist
319 pointer but we can pretend it is here */
320 ptr.to_certinfo = &data->info.certs;
321 *param_slistp = ptr.to_slist;
323 case CURLINFO_TLS_SESSION:
324 case CURLINFO_TLS_SSL_PTR:
326 struct curl_tlssessioninfo **tsip = (struct curl_tlssessioninfo **)
328 struct curl_tlssessioninfo *tsi = &data->tsi;
329 struct connectdata *conn = data->easy_conn;
332 tsi->backend = Curl_ssl_backend();
333 tsi->internals = NULL;
335 if(conn && tsi->backend != CURLSSLBACKEND_NONE) {
337 for(i = 0; i < (sizeof(conn->ssl) / sizeof(conn->ssl[0])); ++i) {
338 if(conn->ssl[i].use) {
339 #if defined(USE_AXTLS)
340 tsi->internals = (void *)conn->ssl[i].ssl;
341 #elif defined(USE_CYASSL)
342 tsi->internals = (void *)conn->ssl[i].handle;
343 #elif defined(USE_DARWINSSL)
344 tsi->internals = (void *)conn->ssl[i].ssl_ctx;
345 #elif defined(USE_GNUTLS)
346 tsi->internals = (void *)conn->ssl[i].session;
347 #elif defined(USE_GSKIT)
348 tsi->internals = (void *)conn->ssl[i].handle;
349 #elif defined(USE_MBEDTLS)
350 tsi->internals = (void *)&conn->ssl[i].ssl;
351 #elif defined(USE_NSS)
352 tsi->internals = (void *)conn->ssl[i].handle;
353 #elif defined(USE_OPENSSL)
354 /* Legacy: CURLINFO_TLS_SESSION must return an SSL_CTX pointer. */
355 tsi->internals = ((info == CURLINFO_TLS_SESSION) ?
356 (void *)conn->ssl[i].ctx :
357 (void *)conn->ssl[i].handle);
358 #elif defined(USE_POLARSSL)
359 tsi->internals = (void *)&conn->ssl[i].ssl;
360 #elif defined(USE_SCHANNEL)
361 tsi->internals = (void *)&conn->ssl[i].ctxt->ctxt_handle;
362 #elif defined(USE_SSL)
363 #error "SSL backend specific information missing for CURLINFO_TLS_SSL_PTR"
372 return CURLE_UNKNOWN_OPTION;
378 static CURLcode getinfo_socket(struct Curl_easy *data, CURLINFO info,
379 curl_socket_t *param_socketp)
382 case CURLINFO_ACTIVESOCKET:
383 *param_socketp = Curl_getconnectinfo(data, NULL);
386 return CURLE_UNKNOWN_OPTION;
392 CURLcode Curl_getinfo(struct Curl_easy *data, CURLINFO info, ...)
395 long *param_longp = NULL;
396 double *param_doublep = NULL;
397 const char **param_charp = NULL;
398 struct curl_slist **param_slistp = NULL;
399 curl_socket_t *param_socketp = NULL;
401 CURLcode result = CURLE_UNKNOWN_OPTION;
408 type = CURLINFO_TYPEMASK & (int)info;
410 case CURLINFO_STRING:
411 param_charp = va_arg(arg, const char **);
413 result = getinfo_char(data, info, param_charp);
416 param_longp = va_arg(arg, long *);
418 result = getinfo_long(data, info, param_longp);
420 case CURLINFO_DOUBLE:
421 param_doublep = va_arg(arg, double *);
423 result = getinfo_double(data, info, param_doublep);
426 param_slistp = va_arg(arg, struct curl_slist **);
428 result = getinfo_slist(data, info, param_slistp);
430 case CURLINFO_SOCKET:
431 param_socketp = va_arg(arg, curl_socket_t *);
433 result = getinfo_socket(data, info, param_socketp);