1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
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.
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.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
22 ***************************************************************************/
26 /* -- WIN32 approved -- */
32 #ifdef HAVE_SYS_TYPES_H
33 #include <sys/types.h>
35 #ifdef HAVE_SYS_STAT_H
43 #if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
47 #ifdef HAVE_SYS_SOCKET_H
48 #include <sys/socket.h>
50 #include <netinet/in.h>
56 #ifdef HAVE_ARPA_INET_H
57 #include <arpa/inet.h>
62 #include <sys/ioctl.h>
65 #ifdef HAVE_SYS_PARAM_H
66 #include <sys/param.h>
69 #ifdef HAVE_SYS_SELECT_H
70 #include <sys/select.h>
73 #endif /* WIN32 ... */
76 #include <curl/curl.h>
87 #define _MPRINTF_REPLACE /* use our functions only */
88 #include <curl/mprintf.h>
90 /* The last #include file should be: */
93 #if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
94 /* win32_cleanup() is for win32 socket cleanup functionality, the opposite
96 static void win32_cleanup(void)
101 /* win32_init() performs win32 socket initialization to properly setup the
102 stack to allow networking */
103 static CURLcode win32_init(void)
105 WORD wVersionRequested;
110 wVersionRequested = MAKEWORD(2, 0);
112 wVersionRequested = MAKEWORD(1, 1);
115 err = WSAStartup(wVersionRequested, &wsaData);
118 /* Tell the user that we couldn't find a useable */
120 return CURLE_FAILED_INIT;
122 /* Confirm that the Windows Sockets DLL supports what we need.*/
123 /* Note that if the DLL supports versions greater */
124 /* than wVersionRequested, it will still return */
125 /* wVersionRequested in wVersion. wHighVersion contains the */
126 /* highest supported version. */
128 if ( LOBYTE( wsaData.wVersion ) != LOBYTE(wVersionRequested) ||
129 HIBYTE( wsaData.wVersion ) != HIBYTE(wVersionRequested) ) {
130 /* Tell the user that we couldn't find a useable */
134 return CURLE_FAILED_INIT;
136 /* The Windows Sockets DLL is acceptable. Proceed. */
141 /* These functions exist merely to prevent compiler warnings */
142 static CURLcode win32_init(void) { return CURLE_OK; }
143 static void win32_cleanup(void) { }
148 * Initialise use of IDNA library.
149 * It falls back to ASCII if $CHARSET isn't defined. This doesn't work for
150 * idna_to_ascii_lz().
152 static void idna_init (void)
158 if (!getenv("CHARSET") && cp > 0) {
159 snprintf(buf, sizeof(buf), "CHARSET=cp%u", cp);
166 #endif /* USE_LIBIDN */
168 /* true globals -- for curl_global_init() and curl_global_cleanup() */
169 static unsigned int initialized;
170 static long init_flags;
173 * If a memory-using function (like curl_getenv) is used before
174 * curl_global_init() is called, we need to have these pointers set already.
178 #define strdup _strdup
181 curl_malloc_callback Curl_cmalloc = (curl_malloc_callback)malloc;
182 curl_free_callback Curl_cfree = (curl_free_callback)free;
183 curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc;
184 curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)strdup;
185 curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc;
188 * curl_global_init() globally initializes cURL given a bitwise set of the
189 * different features of what to initialize.
191 CURLcode curl_global_init(long flags)
196 /* Setup the default memory functions here (again) */
197 Curl_cmalloc = (curl_malloc_callback)malloc;
198 Curl_cfree = (curl_free_callback)free;
199 Curl_crealloc = (curl_realloc_callback)realloc;
200 Curl_cstrdup = (curl_strdup_callback)strdup;
201 Curl_ccalloc = (curl_calloc_callback)calloc;
203 if (flags & CURL_GLOBAL_SSL)
204 if (!Curl_SSL_init())
205 return CURLE_FAILED_INIT;
207 if (flags & CURL_GLOBAL_WIN32)
208 if (win32_init() != CURLE_OK)
209 return CURLE_FAILED_INIT;
213 return CURLE_FAILED_INIT;
227 * curl_global_init_mem() globally initializes cURL and also registers the
228 * user provided callback routines.
230 CURLcode curl_global_init_mem(long flags, curl_malloc_callback m,
231 curl_free_callback f, curl_realloc_callback r,
232 curl_strdup_callback s, curl_calloc_callback c)
234 CURLcode code = CURLE_OK;
236 /* Invalid input, return immediately */
237 if (!m || !f || !r || !s || !c)
238 return CURLE_FAILED_INIT;
240 /* Already initialized, don't do it again */
244 /* Call the actual init function first */
245 code = curl_global_init(flags);
246 if (code == CURLE_OK) {
258 * curl_global_cleanup() globally cleanups cURL, uses the value of
259 * "init_flags" to determine what needs to be cleaned up and what doesn't.
261 void curl_global_cleanup(void)
266 Curl_global_host_cache_dtor();
268 if (init_flags & CURL_GLOBAL_SSL)
271 if (init_flags & CURL_GLOBAL_WIN32)
283 * curl_easy_init() is the external interface to alloc, setup and init an
284 * easy handle that is returned. If anything goes wrong, NULL is returned.
286 CURL *curl_easy_init(void)
289 struct SessionHandle *data;
291 /* Make sure we inited the global SSL stuff */
293 res = curl_global_init(CURL_GLOBAL_DEFAULT);
295 /* something in the global init failed, return nothing */
299 /* We use curl_open() with undefined URL so far */
300 res = Curl_open(&data);
308 * curl_easy_setopt() is the external interface for setting options on an
311 typedef int (*func_T)(void);
312 CURLcode curl_easy_setopt(CURL *curl, CURLoption tag, ...)
315 func_T param_func = (func_T)0;
317 void *param_obj = NULL;
318 curl_off_t param_offset = 0;
319 struct SessionHandle *data = curl;
320 CURLcode ret=CURLE_FAILED_INIT;
323 return CURLE_BAD_FUNCTION_ARGUMENT;
328 Object pointers can't necessarily be casted to function pointers and
329 therefore we need to know what type it is and read the correct type
330 at once. This should also correct problems with different sizes of
334 if(tag < CURLOPTTYPE_OBJECTPOINT) {
335 /* This is a LONG type */
336 param_long = va_arg(arg, long);
337 ret = Curl_setopt(data, tag, param_long);
339 else if(tag < CURLOPTTYPE_FUNCTIONPOINT) {
340 /* This is a object pointer type */
341 param_obj = va_arg(arg, void *);
342 ret = Curl_setopt(data, tag, param_obj);
344 else if(tag < CURLOPTTYPE_OFF_T) {
345 /* This is a function pointer type */
346 param_func = va_arg(arg, func_T );
347 ret = Curl_setopt(data, tag, param_func);
350 /* This is a curl_off_t type */
351 param_offset = va_arg(arg, curl_off_t);
352 ret = Curl_setopt(data, tag, param_offset);
359 #ifdef CURL_MULTIEASY
360 /***************************************************************************
361 * This function is still only for testing purposes. It makes a great way
362 * to run the full test suite on the multi interface instead of the easy one.
363 ***************************************************************************
365 * The *new* curl_easy_perform() is the external interface that performs a
366 * transfer previously setup.
368 * Wrapper-function that: creates a multi handle, adds the easy handle to it,
369 * runs curl_multi_perform() until the transfer is done, then detaches the
370 * easy handle, destroys the multi handle and returns the easy handle's return
371 * code. This will make everything internally use and assume multi interface.
373 CURLcode curl_easy_perform(CURL *easy)
377 CURLcode code = CURLE_OK;
379 struct timeval timeout;
388 return CURLE_BAD_FUNCTION_ARGUMENT;
390 multi = curl_multi_init();
392 return CURLE_OUT_OF_MEMORY;
394 mcode = curl_multi_add_handle(multi, easy);
396 curl_multi_cleanup(multi);
397 return CURLE_FAILED_INIT;
400 /* we start some action by calling perform right away */
403 while(CURLM_CALL_MULTI_PERFORM ==
404 curl_multi_perform(multi, &still_running));
413 /* timeout once per second */
417 /* get file descriptors from the transfers */
418 curl_multi_fdset(multi, &fdread, &fdwrite, &fdexcep, &maxfd);
420 rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
426 /* timeout or data to send/receive => loop! */
427 } while(still_running);
429 msg = curl_multi_info_read(multi, &rc);
431 code = msg->data.result;
433 mcode = curl_multi_remove_handle(multi, easy);
434 /* what to do if it fails? */
436 mcode = curl_multi_cleanup(multi);
437 /* what to do if it fails? */
443 * curl_easy_perform() is the external interface that performs a transfer
446 CURLcode curl_easy_perform(CURL *curl)
448 struct SessionHandle *data = (struct SessionHandle *)curl;
451 return CURLE_BAD_FUNCTION_ARGUMENT;
453 if ( ! (data->share && data->share->hostcache) ) {
455 if (Curl_global_host_cache_use(data) &&
456 data->hostcache != Curl_global_host_cache_get()) {
458 Curl_hash_destroy(data->hostcache);
459 data->hostcache = Curl_global_host_cache_get();
462 if (!data->hostcache) {
463 data->hostcache = Curl_mk_dnscache();
466 /* While we possibly could survive and do good without a host cache,
467 the fact that creating it failed indicates that things are truly
468 screwed up and we should bail out! */
469 return CURLE_OUT_OF_MEMORY;
474 return Curl_perform(data);
479 * curl_easy_cleanup() is the external interface to cleaning/freeing the given
482 void curl_easy_cleanup(CURL *curl)
484 struct SessionHandle *data = (struct SessionHandle *)curl;
493 * Store a pointed to the multi handle within the easy handle's data struct.
495 void Curl_easy_addmulti(struct SessionHandle *data,
502 * curl_easy_getinfo() is an external interface that allows an app to retrieve
503 * information from a performed transfer and similar.
505 CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...)
509 struct SessionHandle *data = (struct SessionHandle *)curl;
512 paramp = va_arg(arg, void *);
514 return Curl_getinfo(data, info, paramp);
518 * curl_easy_duphandle() is an external interface to allow duplication of a
519 * given input easy handle. The returned handle will be a new working handle
520 * with all options set exactly as the input source handle.
522 CURL *curl_easy_duphandle(CURL *incurl)
525 struct SessionHandle *data=(struct SessionHandle *)incurl;
527 struct SessionHandle *outcurl = (struct SessionHandle *)
528 calloc(sizeof(struct SessionHandle), 1);
531 return NULL; /* failure */
536 * We setup a few buffers we need. We should probably make them
537 * get setup on-demand in the code, as that would probably decrease
538 * the likeliness of us forgetting to init a buffer here in the future.
540 outcurl->state.headerbuff=(char*)malloc(HEADERSIZE);
541 if(!outcurl->state.headerbuff) {
544 outcurl->state.headersize=HEADERSIZE;
546 /* copy all userdefined values */
547 outcurl->set = data->set;
548 outcurl->state.numconnects = data->state.numconnects;
549 outcurl->state.connects = (struct connectdata **)
550 malloc(sizeof(struct connectdata *) * outcurl->state.numconnects);
552 if(!outcurl->state.connects) {
556 memset(outcurl->state.connects, 0,
557 sizeof(struct connectdata *)*outcurl->state.numconnects);
559 outcurl->progress.flags = data->progress.flags;
560 outcurl->progress.callback = data->progress.callback;
562 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
564 /* If cookies are enabled in the parent handle, we enable them
565 in the clone as well! */
566 outcurl->cookies = Curl_cookie_init(data,
567 data->cookies->filename,
569 data->set.cookiesession);
570 if(!outcurl->cookies) {
574 #endif /* CURL_DISABLE_HTTP */
576 /* duplicate all values in 'change' */
577 if(data->change.url) {
578 outcurl->change.url = strdup(data->change.url);
579 if(!outcurl->change.url)
581 outcurl->change.url_alloc = TRUE;
583 if(data->change.proxy) {
584 outcurl->change.proxy = strdup(data->change.proxy);
585 if(!outcurl->change.proxy)
587 outcurl->change.proxy_alloc = TRUE;
589 if(data->change.referer) {
590 outcurl->change.referer = strdup(data->change.referer);
591 if(!outcurl->change.referer)
593 outcurl->change.referer_alloc = TRUE;
597 /* If we use ares, we setup a new ares channel for the new handle */
598 if(ARES_SUCCESS != ares_init(&outcurl->state.areschannel))
602 fail = FALSE; /* we reach this point and thus we are OK */
608 if(outcurl->state.connects)
609 free(outcurl->state.connects);
610 if(outcurl->state.headerbuff)
611 free(outcurl->state.headerbuff);
612 if(outcurl->change.proxy)
613 free(outcurl->change.proxy);
614 if(outcurl->change.url)
615 free(outcurl->change.url);
616 if(outcurl->change.referer)
617 free(outcurl->change.referer);
618 free(outcurl); /* free the memory again */
627 * curl_easy_reset() is an external interface that allows an app to re-
628 * initialize a session handle to the default values.
630 void curl_easy_reset(CURL *curl)
632 struct SessionHandle *data = (struct SessionHandle *)curl;
634 /* zero out UserDefined data: */
635 memset(&data->set, 0, sizeof(struct UserDefined));
637 /* zero out Progress data: */
638 memset(&data->progress, 0, sizeof(struct Progress));
640 /* The remainder of these calls have been taken from Curl_open() */
642 data->set.out = stdout; /* default output to stdout */
643 data->set.in = stdin; /* default input from stdin */
644 data->set.err = stderr; /* default stderr to stderr */
646 /* use fwrite as default function to store output */
647 data->set.fwrite = (curl_write_callback)fwrite;
649 /* use fread as default function to read input */
650 data->set.fread = (curl_read_callback)fread;
652 data->set.infilesize = -1; /* we don't know any size */
653 data->set.postfieldsize = -1;
655 data->state.current_speed = -1; /* init to negative == impossible */
657 data->set.httpreq = HTTPREQ_GET; /* Default HTTP request */
658 data->set.ftp_use_epsv = TRUE; /* FTP defaults to EPSV operations */
659 data->set.ftp_use_eprt = TRUE; /* FTP defaults to EPRT operations */
661 data->set.dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
663 /* make libcurl quiet by default: */
664 data->set.hide_progress = TRUE; /* CURLOPT_NOPROGRESS changes these */
665 data->progress.flags |= PGRS_HIDE;
667 /* Set the default size of the SSL session ID cache */
668 data->set.ssl.numsessions = 5;
670 data->set.proxyport = 1080;
671 data->set.proxytype = CURLPROXY_HTTP; /* defaults to HTTP proxy */
672 data->set.httpauth = CURLAUTH_BASIC; /* defaults to basic */
673 data->set.proxyauth = CURLAUTH_BASIC; /* defaults to basic */
676 * libcurl 7.10 introduced SSL verification *by default*! This needs to be
677 * switched off unless wanted.
679 data->set.ssl.verifypeer = TRUE;
680 data->set.ssl.verifyhost = 2;
681 #ifdef CURL_CA_BUNDLE
682 /* This is our prefered CA cert bundle since install time */
683 data->set.ssl.CAfile = (char *)CURL_CA_BUNDLE;