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