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