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