1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2010, 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 http://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 "setup.h" 24 25#include <curl/curl.h> 26 27#include "urldata.h" 28#include "getinfo.h" 29 30#include "curl_memory.h" 31#include "sslgen.h" 32#include "connect.h" /* Curl_getconnectinfo() */ 33#include "progress.h" 34 35/* Make this the last #include */ 36#include "memdebug.h" 37 38/* 39 * This is supposed to be called in the beginning of a perform() session 40 * and should reset all session-info variables 41 */ 42CURLcode Curl_initinfo(struct SessionHandle *data) 43{ 44 struct Progress *pro = &data->progress; 45 struct PureInfo *info =&data->info; 46 47 pro->t_nslookup = 0; 48 pro->t_connect = 0; 49 pro->t_pretransfer = 0; 50 pro->t_starttransfer = 0; 51 pro->timespent = 0; 52 pro->t_redirect = 0; 53 54 info->httpcode = 0; 55 info->httpversion=0; 56 info->filetime=-1; /* -1 is an illegal time and thus means unknown */ 57 58 if(info->contenttype) 59 free(info->contenttype); 60 info->contenttype = NULL; 61 62 info->header_size = 0; 63 info->request_size = 0; 64 info->numconnects = 0; 65 66 info->conn_primary_ip[0] = '\0'; 67 info->conn_local_ip[0] = '\0'; 68 info->conn_primary_port = 0; 69 info->conn_local_port = 0; 70 71 return CURLE_OK; 72} 73 74CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...) 75{ 76 va_list arg; 77 long *param_longp=NULL; 78 double *param_doublep=NULL; 79 char **param_charp=NULL; 80 struct curl_slist **param_slistp=NULL; 81 int type; 82 curl_socket_t sockfd; 83 84 union { 85 struct curl_certinfo * to_certinfo; 86 struct curl_slist * to_slist; 87 } ptr; 88 89 if(!data) 90 return CURLE_BAD_FUNCTION_ARGUMENT; 91 92 va_start(arg, info); 93 94 type = CURLINFO_TYPEMASK & (int)info; 95 switch(type) { 96 case CURLINFO_STRING: 97 param_charp = va_arg(arg, char **); 98 if(NULL == param_charp) 99 return CURLE_BAD_FUNCTION_ARGUMENT; 100 break; 101 case CURLINFO_LONG: 102 param_longp = va_arg(arg, long *); 103 if(NULL == param_longp) 104 return CURLE_BAD_FUNCTION_ARGUMENT; 105 break; 106 case CURLINFO_DOUBLE: 107 param_doublep = va_arg(arg, double *); 108 if(NULL == param_doublep) 109 return CURLE_BAD_FUNCTION_ARGUMENT; 110 break; 111 case CURLINFO_SLIST: 112 param_slistp = va_arg(arg, struct curl_slist **); 113 if(NULL == param_slistp) 114 return CURLE_BAD_FUNCTION_ARGUMENT; 115 break; 116 default: 117 return CURLE_BAD_FUNCTION_ARGUMENT; 118 } 119 120 switch(info) { 121 case CURLINFO_EFFECTIVE_URL: 122 *param_charp = data->change.url?data->change.url:(char *)""; 123 break; 124 case CURLINFO_RESPONSE_CODE: 125 *param_longp = data->info.httpcode; 126 break; 127 case CURLINFO_HTTP_CONNECTCODE: 128 *param_longp = data->info.httpproxycode; 129 break; 130 case CURLINFO_FILETIME: 131 *param_longp = data->info.filetime; 132 break; 133 case CURLINFO_HEADER_SIZE: 134 *param_longp = data->info.header_size; 135 break; 136 case CURLINFO_REQUEST_SIZE: 137 *param_longp = data->info.request_size; 138 break; 139 case CURLINFO_TOTAL_TIME: 140 *param_doublep = data->progress.timespent; 141 break; 142 case CURLINFO_NAMELOOKUP_TIME: 143 *param_doublep = data->progress.t_nslookup; 144 break; 145 case CURLINFO_CONNECT_TIME: 146 *param_doublep = data->progress.t_connect; 147 break; 148 case CURLINFO_APPCONNECT_TIME: 149 *param_doublep = data->progress.t_appconnect; 150 break; 151 case CURLINFO_PRETRANSFER_TIME: 152 *param_doublep = data->progress.t_pretransfer; 153 break; 154 case CURLINFO_STARTTRANSFER_TIME: 155 *param_doublep = data->progress.t_starttransfer; 156 break; 157 case CURLINFO_SIZE_UPLOAD: 158 *param_doublep = (double)data->progress.uploaded; 159 break; 160 case CURLINFO_SIZE_DOWNLOAD: 161 *param_doublep = (double)data->progress.downloaded; 162 break; 163 case CURLINFO_SPEED_DOWNLOAD: 164 *param_doublep = (double)data->progress.dlspeed; 165 break; 166 case CURLINFO_SPEED_UPLOAD: 167 *param_doublep = (double)data->progress.ulspeed; 168 break; 169 case CURLINFO_SSL_VERIFYRESULT: 170 *param_longp = data->set.ssl.certverifyresult; 171 break; 172 case CURLINFO_CONTENT_LENGTH_DOWNLOAD: 173 *param_doublep = (data->progress.flags & PGRS_DL_SIZE_KNOWN)? 174 (double)data->progress.size_dl:-1; 175 break; 176 case CURLINFO_CONTENT_LENGTH_UPLOAD: 177 *param_doublep = (data->progress.flags & PGRS_UL_SIZE_KNOWN)? 178 (double)data->progress.size_ul:-1; 179 break; 180 case CURLINFO_REDIRECT_TIME: 181 *param_doublep = data->progress.t_redirect; 182 break; 183 case CURLINFO_REDIRECT_COUNT: 184 *param_longp = data->set.followlocation; 185 break; 186 case CURLINFO_CONTENT_TYPE: 187 *param_charp = data->info.contenttype; 188 break; 189 case CURLINFO_PRIVATE: 190 *param_charp = (char *) data->set.private_data; 191 break; 192 case CURLINFO_HTTPAUTH_AVAIL: 193 *param_longp = data->info.httpauthavail; 194 break; 195 case CURLINFO_PROXYAUTH_AVAIL: 196 *param_longp = data->info.proxyauthavail; 197 break; 198 case CURLINFO_OS_ERRNO: 199 *param_longp = data->state.os_errno; 200 break; 201 case CURLINFO_NUM_CONNECTS: 202 *param_longp = data->info.numconnects; 203 break; 204 case CURLINFO_SSL_ENGINES: 205 *param_slistp = Curl_ssl_engines_list(data); 206 break; 207 case CURLINFO_COOKIELIST: 208 *param_slistp = Curl_cookie_list(data); 209 break; 210 case CURLINFO_FTP_ENTRY_PATH: 211 /* Return the entrypath string from the most recent connection. 212 This pointer was copied from the connectdata structure by FTP. 213 The actual string may be free()ed by subsequent libcurl calls so 214 it must be copied to a safer area before the next libcurl call. 215 Callers must never free it themselves. */ 216 *param_charp = data->state.most_recent_ftp_entrypath; 217 break; 218 case CURLINFO_LASTSOCKET: 219 sockfd = Curl_getconnectinfo(data, NULL); 220 221 /* note: this is not a good conversion for systems with 64 bit sockets and 222 32 bit longs */ 223 if(sockfd != CURL_SOCKET_BAD) 224 *param_longp = (long)sockfd; 225 else 226 /* this interface is documented to return -1 in case of badness, which 227 may not be the same as the CURL_SOCKET_BAD value */ 228 *param_longp = -1; 229 break; 230 case CURLINFO_REDIRECT_URL: 231 /* Return the URL this request would have been redirected to if that 232 option had been enabled! */ 233 *param_charp = data->info.wouldredirect; 234 break; 235 case CURLINFO_PRIMARY_IP: 236 /* Return the ip address of the most recent (primary) connection */ 237 *param_charp = data->info.conn_primary_ip; 238 break; 239 case CURLINFO_PRIMARY_PORT: 240 /* Return the (remote) port of the most recent (primary) connection */ 241 *param_longp = data->info.conn_primary_port; 242 break; 243 case CURLINFO_LOCAL_IP: 244 /* Return the source/local ip address of the most recent (primary) 245 connection */ 246 *param_charp = data->info.conn_local_ip; 247 break; 248 case CURLINFO_LOCAL_PORT: 249 /* Return the local port of the most recent (primary) connection */ 250 *param_longp = data->info.conn_local_port; 251 break; 252 case CURLINFO_CERTINFO: 253 /* Return the a pointer to the certinfo struct. Not really an slist 254 pointer but we can pretend it is here */ 255 ptr.to_certinfo = &data->info.certs; 256 *param_slistp = ptr.to_slist; 257 break; 258 case CURLINFO_CONDITION_UNMET: 259 /* return if the condition prevented the document to get transferred */ 260 *param_longp = data->info.timecond; 261 break; 262 case CURLINFO_RTSP_SESSION_ID: 263 *param_charp = data->set.str[STRING_RTSP_SESSION_ID]; 264 break; 265 case CURLINFO_RTSP_CLIENT_CSEQ: 266 *param_longp = data->state.rtsp_next_client_CSeq; 267 break; 268 case CURLINFO_RTSP_SERVER_CSEQ: 269 *param_longp = data->state.rtsp_next_server_CSeq; 270 break; 271 case CURLINFO_RTSP_CSEQ_RECV: 272 *param_longp = data->state.rtsp_CSeq_recv; 273 break; 274 275 default: 276 return CURLE_BAD_FUNCTION_ARGUMENT; 277 } 278 return CURLE_OK; 279} 280