gnutls: don't use deprecated type names anymore
[platform/upstream/curl.git] / lib / getinfo.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2014, 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 "vtls/vtls.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   case CURLINFO_TLS_SESSION:
281     {
282       struct curl_tlssessioninfo **tsip = (struct curl_tlssessioninfo **)
283                                           param_slistp;
284       struct curl_tlssessioninfo *tsi = &data->tsi;
285       struct connectdata *conn = data->easy_conn;
286       unsigned int sockindex = 0;
287
288       *tsip = tsi;
289       tsi->backend = CURLSSLBACKEND_NONE;
290       tsi->internals = NULL;
291
292       if(!conn)
293         break;
294
295       /* Find the active ("in use") SSL connection, if any */
296       while((sockindex < sizeof(conn->ssl) / sizeof(conn->ssl[0])) &&
297             (!conn->ssl[sockindex].use))
298         sockindex++;
299
300       if(sockindex == sizeof(conn->ssl) / sizeof(conn->ssl[0]))
301         break; /* no SSL session found */
302
303       /* Return the TLS session information from the relevant backend */
304 #ifdef USE_SSLEAY
305       tsi->backend = CURLSSLBACKEND_OPENSSL;
306       tsi->internals = conn->ssl[sockindex].ctx;
307 #endif
308 #ifdef USE_GNUTLS
309       tsi->backend = CURLSSLBACKEND_GNUTLS;
310       tsi->internals = conn->ssl[sockindex].session;
311 #endif
312 #ifdef USE_NSS
313       tsi->backend = CURLSSLBACKEND_NSS;
314       tsi->internals = conn->ssl[sockindex].handle;
315 #endif
316 #ifdef USE_QSOSSL
317       tsi->backend = CURLSSLBACKEND_QSOSSL;
318       tsi->internals = conn->ssl[sockindex].handle;
319 #endif
320 #ifdef USE_GSKIT
321       tsi->backend = CURLSSLBACKEND_GSKIT;
322       tsi->internals = conn->ssl[sockindex].handle;
323 #endif
324       /* NOTE: For other SSL backends, it is not immediately clear what data
325          to return from 'struct ssl_connect_data'; thus, for now we keep the
326          backend as CURLSSLBACKEND_NONE in those cases, which should be
327          interpreted as "not supported" */
328     }
329     break;
330   default:
331     return CURLE_BAD_FUNCTION_ARGUMENT;
332   }
333   return CURLE_OK;
334 }
335
336 CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...)
337 {
338   va_list arg;
339   long *param_longp=NULL;
340   double *param_doublep=NULL;
341   char **param_charp=NULL;
342   struct curl_slist **param_slistp=NULL;
343   int type;
344   /* default return code is to error out! */
345   CURLcode ret = CURLE_BAD_FUNCTION_ARGUMENT;
346
347   if(!data)
348     return ret;
349
350   va_start(arg, info);
351
352   type = CURLINFO_TYPEMASK & (int)info;
353   switch(type) {
354   case CURLINFO_STRING:
355     param_charp = va_arg(arg, char **);
356     if(NULL != param_charp)
357       ret = getinfo_char(data, info, param_charp);
358     break;
359   case CURLINFO_LONG:
360     param_longp = va_arg(arg, long *);
361     if(NULL != param_longp)
362       ret = getinfo_long(data, info, param_longp);
363     break;
364   case CURLINFO_DOUBLE:
365     param_doublep = va_arg(arg, double *);
366     if(NULL != param_doublep)
367       ret = getinfo_double(data, info, param_doublep);
368     break;
369   case CURLINFO_SLIST:
370     param_slistp = va_arg(arg, struct curl_slist **);
371     if(NULL != param_slistp)
372       ret = getinfo_slist(data, info, param_slistp);
373     break;
374   default:
375     break;
376   }
377
378   va_end(arg);
379   return ret;
380 }