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