1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2004, 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.
21 * $Id: easy.c,v 1.49 2004/03/15 16:28:36 bagder Exp $
22 ***************************************************************************/
26 /* -- WIN32 approved -- */
32 #include <sys/types.h>
39 #if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
43 #ifdef HAVE_SYS_SOCKET_H
44 #include <sys/socket.h>
46 #include <netinet/in.h>
52 #ifdef HAVE_ARPA_INET_H
53 #include <arpa/inet.h>
58 #include <sys/ioctl.h>
61 #ifdef HAVE_SYS_PARAM_H
62 #include <sys/param.h>
65 #ifdef HAVE_SYS_SELECT_H
66 #include <sys/select.h>
72 #include <curl/curl.h>
80 #define _MPRINTF_REPLACE /* use our functions only */
81 #include <curl/mprintf.h>
83 /* The last #include file should be: */
88 /* Silly win32 socket initialization functions */
90 #if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
91 static void win32_cleanup(void)
96 static CURLcode win32_init(void)
98 WORD wVersionRequested;
103 wVersionRequested = MAKEWORD(2, 0);
105 wVersionRequested = MAKEWORD(1, 1);
108 err = WSAStartup(wVersionRequested, &wsaData);
111 /* Tell the user that we couldn't find a useable */
113 return CURLE_FAILED_INIT;
115 /* Confirm that the Windows Sockets DLL supports what we need.*/
116 /* Note that if the DLL supports versions greater */
117 /* than wVersionRequested, it will still return */
118 /* wVersionRequested in wVersion. wHighVersion contains the */
119 /* highest supported version. */
121 if ( LOBYTE( wsaData.wVersion ) != LOBYTE(wVersionRequested) ||
122 HIBYTE( wsaData.wVersion ) != HIBYTE(wVersionRequested) ) {
123 /* Tell the user that we couldn't find a useable */
127 return CURLE_FAILED_INIT;
131 /* The Windows Sockets DLL is acceptable. Proceed. */
133 /* These functions exist merely to prevent compiler warnings */
134 static CURLcode win32_init(void) { return CURLE_OK; }
135 static void win32_cleanup(void) { }
139 /* true globals -- for curl_global_init() and curl_global_cleanup() */
140 static unsigned int initialized = 0;
141 static long init_flags = 0;
144 * Globally initializes cURL given a bitwise set of
145 * the different features to initialize.
147 CURLcode curl_global_init(long flags)
152 if (flags & CURL_GLOBAL_SSL)
155 if (flags & CURL_GLOBAL_WIN32)
156 if (win32_init() != CURLE_OK)
157 return CURLE_FAILED_INIT;
161 return CURLE_FAILED_INIT;
171 * Globally cleanup cURL, uses the value of "init_flags" to determine
172 * what needs to be cleaned up and what doesn't
174 void curl_global_cleanup(void)
179 Curl_global_host_cache_dtor();
181 if (init_flags & CURL_GLOBAL_SSL)
184 if (init_flags & CURL_GLOBAL_WIN32)
195 CURL *curl_easy_init(void)
198 struct SessionHandle *data;
200 /* Make sure we inited the global SSL stuff */
202 res = curl_global_init(CURL_GLOBAL_DEFAULT);
204 /* something in the global init failed, return nothing */
208 /* We use curl_open() with undefined URL so far */
209 res = Curl_open(&data);
216 typedef int (*func_T)(void);
217 CURLcode curl_easy_setopt(CURL *curl, CURLoption tag, ...)
220 func_T param_func = (func_T)0;
222 void *param_obj = NULL;
223 curl_off_t param_offset = 0;
224 struct SessionHandle *data = curl;
225 CURLcode ret=CURLE_FAILED_INIT;
230 Object pointers can't necessarily be casted to function pointers and
231 therefore we need to know what type it is and read the correct type
232 at once. This should also correct problems with different sizes of
236 if(tag < CURLOPTTYPE_OBJECTPOINT) {
237 /* This is a LONG type */
238 param_long = va_arg(arg, long);
239 ret = Curl_setopt(data, tag, param_long);
241 else if(tag < CURLOPTTYPE_FUNCTIONPOINT) {
242 /* This is a object pointer type */
243 param_obj = va_arg(arg, void *);
244 ret = Curl_setopt(data, tag, param_obj);
246 else if(tag < CURLOPTTYPE_OFF_T) {
247 /* This is a function pointer type */
248 param_func = va_arg(arg, func_T );
249 ret = Curl_setopt(data, tag, param_func);
251 /* This is a curl_off_t type */
252 param_offset = va_arg(arg, curl_off_t);
253 ret = Curl_setopt(data, tag, param_offset);
260 CURLcode curl_easy_perform(CURL *curl)
262 struct SessionHandle *data = (struct SessionHandle *)curl;
264 if ( ! (data->share && data->share->hostcache) ) {
266 if (Curl_global_host_cache_use(data) &&
267 data->hostcache != Curl_global_host_cache_get()) {
269 Curl_hash_destroy(data->hostcache);
270 data->hostcache = Curl_global_host_cache_get();
273 if (!data->hostcache) {
274 data->hostcache = Curl_hash_alloc(7, Curl_freednsinfo);
277 /* While we possibly could survive and do good without a host cache,
278 the fact that creating it failed indicates that things are truly
279 screwed up and we should bail out! */
280 return CURLE_OUT_OF_MEMORY;
285 return Curl_perform(data);
288 void curl_easy_cleanup(CURL *curl)
290 struct SessionHandle *data = (struct SessionHandle *)curl;
291 if ( ! (data->share && data->share->hostcache) ) {
292 if ( !Curl_global_host_cache_use(data)) {
293 Curl_hash_destroy(data->hostcache);
299 CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...)
303 struct SessionHandle *data = (struct SessionHandle *)curl;
306 paramp = va_arg(arg, void *);
308 return Curl_getinfo(data, info, paramp);
311 CURL *curl_easy_duphandle(CURL *incurl)
313 struct SessionHandle *data=(struct SessionHandle *)incurl;
315 struct SessionHandle *outcurl = (struct SessionHandle *)
316 malloc(sizeof(struct SessionHandle));
319 return NULL; /* failure */
321 /* start with clearing the entire new struct */
322 memset(outcurl, 0, sizeof(struct SessionHandle));
325 * We setup a few buffers we need. We should probably make them
326 * get setup on-demand in the code, as that would probably decrease
327 * the likeliness of us forgetting to init a buffer here in the future.
329 outcurl->state.headerbuff=(char*)malloc(HEADERSIZE);
330 if(!outcurl->state.headerbuff) {
331 free(outcurl); /* free the memory again */
334 outcurl->state.headersize=HEADERSIZE;
336 /* copy all userdefined values */
337 outcurl->set = data->set;
338 outcurl->state.numconnects = data->state.numconnects;
339 outcurl->state.connects = (struct connectdata **)
340 malloc(sizeof(struct connectdata *) * outcurl->state.numconnects);
342 if(!outcurl->state.connects) {
343 free(outcurl->state.headerbuff);
347 memset(outcurl->state.connects, 0,
348 sizeof(struct connectdata *)*outcurl->state.numconnects);
350 outcurl->progress.flags = data->progress.flags;
351 outcurl->progress.callback = data->progress.callback;
354 /* If cookies are enabled in the parent handle, we enable them
355 in the clone as well! */
356 outcurl->cookies = Curl_cookie_init(data,
357 data->cookies->filename,
359 data->set.cookiesession);
361 /* duplicate all values in 'change' */
362 if(data->change.url) {
363 outcurl->change.url = strdup(data->change.url);
364 outcurl->change.url_alloc = TRUE;
366 if(data->change.proxy) {
367 outcurl->change.proxy = strdup(data->change.proxy);
368 outcurl->change.proxy_alloc = TRUE;
370 if(data->change.referer) {
371 outcurl->change.referer = strdup(data->change.referer);
372 outcurl->change.referer_alloc = TRUE;