Git init
[external/curl.git] / lib / easy.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2010, 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 /* -- WIN32 approved -- */
26 #include <stdio.h>
27 #include <string.h>
28 #include <stdarg.h>
29 #include <stdlib.h>
30 #include <ctype.h>
31 #include <errno.h>
32
33 #include "strequal.h"
34
35 #ifdef WIN32
36 #include <time.h>
37 #include <io.h>
38 #else
39 #ifdef HAVE_SYS_SOCKET_H
40 #include <sys/socket.h>
41 #endif
42 #ifdef HAVE_NETINET_IN_H
43 #include <netinet/in.h>
44 #endif
45 #ifdef HAVE_SYS_TIME_H
46 #include <sys/time.h>
47 #endif
48 #ifdef HAVE_UNISTD_H
49 #include <unistd.h>
50 #endif
51 #ifdef HAVE_NETDB_H
52 #include <netdb.h>
53 #endif
54 #ifdef HAVE_ARPA_INET_H
55 #include <arpa/inet.h>
56 #endif
57 #ifdef HAVE_NET_IF_H
58 #include <net/if.h>
59 #endif
60 #ifdef HAVE_SYS_IOCTL_H
61 #include <sys/ioctl.h>
62 #endif
63
64 #ifdef HAVE_SYS_PARAM_H
65 #include <sys/param.h>
66 #endif
67
68 #endif  /* WIN32 ... */
69
70 #include "urldata.h"
71 #include <curl/curl.h>
72 #include "transfer.h"
73 #include "sslgen.h"
74 #include "url.h"
75 #include "getinfo.h"
76 #include "hostip.h"
77 #include "share.h"
78 #include "strdup.h"
79 #include "curl_memory.h"
80 #include "progress.h"
81 #include "easyif.h"
82 #include "select.h"
83 #include "sendf.h" /* for failf function prototype */
84 #include "http_ntlm.h"
85 #include "connect.h" /* for Curl_getconnectinfo */
86 #include "slist.h"
87 #include "curl_rand.h"
88
89 #define _MPRINTF_REPLACE /* use our functions only */
90 #include <curl/mprintf.h>
91
92 #if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
93 #include <iconv.h>
94 /* set default codesets for iconv */
95 #ifndef CURL_ICONV_CODESET_OF_NETWORK
96 #define CURL_ICONV_CODESET_OF_NETWORK "ISO8859-1"
97 #endif
98 #ifndef CURL_ICONV_CODESET_FOR_UTF8
99 #define CURL_ICONV_CODESET_FOR_UTF8   "UTF-8"
100 #endif
101 #define ICONV_ERROR  (size_t)-1
102 #endif /* CURL_DOES_CONVERSIONS && HAVE_ICONV */
103
104 /* The last #include file should be: */
105 #include "memdebug.h"
106
107 /* win32_cleanup() is for win32 socket cleanup functionality, the opposite
108    of win32_init() */
109 static void win32_cleanup(void)
110 {
111 #ifdef USE_WINSOCK
112   WSACleanup();
113 #endif
114 #ifdef USE_WINDOWS_SSPI
115   Curl_sspi_global_cleanup();
116 #endif
117 }
118
119 /* win32_init() performs win32 socket initialization to properly setup the
120    stack to allow networking */
121 static CURLcode win32_init(void)
122 {
123 #ifdef USE_WINSOCK
124   WORD wVersionRequested;
125   WSADATA wsaData;
126   int res;
127
128 #if defined(ENABLE_IPV6) && (USE_WINSOCK < 2)
129   Error IPV6_requires_winsock2
130 #endif
131
132   wVersionRequested = MAKEWORD(USE_WINSOCK, USE_WINSOCK);
133
134   res = WSAStartup(wVersionRequested, &wsaData);
135
136   if(res != 0)
137     /* Tell the user that we couldn't find a useable */
138     /* winsock.dll.     */
139     return CURLE_FAILED_INIT;
140
141   /* Confirm that the Windows Sockets DLL supports what we need.*/
142   /* Note that if the DLL supports versions greater */
143   /* than wVersionRequested, it will still return */
144   /* wVersionRequested in wVersion. wHighVersion contains the */
145   /* highest supported version. */
146
147   if( LOBYTE( wsaData.wVersion ) != LOBYTE(wVersionRequested) ||
148        HIBYTE( wsaData.wVersion ) != HIBYTE(wVersionRequested) ) {
149     /* Tell the user that we couldn't find a useable */
150
151     /* winsock.dll. */
152     WSACleanup();
153     return CURLE_FAILED_INIT;
154   }
155   /* The Windows Sockets DLL is acceptable. Proceed. */
156 #endif
157
158 #ifdef USE_WINDOWS_SSPI
159   {
160     CURLcode err = Curl_sspi_global_init();
161     if (err != CURLE_OK)
162       return err;
163   }
164 #endif
165
166   return CURLE_OK;
167 }
168
169 #ifdef USE_LIBIDN
170 /*
171  * Initialise use of IDNA library.
172  * It falls back to ASCII if $CHARSET isn't defined. This doesn't work for
173  * idna_to_ascii_lz().
174  */
175 static void idna_init (void)
176 {
177 #ifdef WIN32
178   char buf[60];
179   UINT cp = GetACP();
180
181   if(!getenv("CHARSET") && cp > 0) {
182     snprintf(buf, sizeof(buf), "CHARSET=cp%u", cp);
183     putenv(buf);
184   }
185 #else
186   /* to do? */
187 #endif
188 }
189 #endif  /* USE_LIBIDN */
190
191 /* true globals -- for curl_global_init() and curl_global_cleanup() */
192 static unsigned int  initialized;
193 static long          init_flags;
194
195 /*
196  * strdup (and other memory functions) is redefined in complicated
197  * ways, but at this point it must be defined as the system-supplied strdup
198  * so the callback pointer is initialized correctly.
199  */
200 #if defined(_WIN32_WCE)
201 #define system_strdup _strdup
202 #elif !defined(HAVE_STRDUP)
203 #define system_strdup curlx_strdup
204 #else
205 #define system_strdup strdup
206 #endif
207
208 #if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__)
209 #  pragma warning(disable:4232) /* MSVC extension, dllimport identity */
210 #endif
211
212 #ifndef __SYMBIAN32__
213 /*
214  * If a memory-using function (like curl_getenv) is used before
215  * curl_global_init() is called, we need to have these pointers set already.
216  */
217 curl_malloc_callback Curl_cmalloc = (curl_malloc_callback)malloc;
218 curl_free_callback Curl_cfree = (curl_free_callback)free;
219 curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc;
220 curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)system_strdup;
221 curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc;
222 #else
223 /*
224  * Symbian OS doesn't support initialization to code in writeable static data.
225  * Initialization will occur in the curl_global_init() call.
226  */
227 curl_malloc_callback Curl_cmalloc;
228 curl_free_callback Curl_cfree;
229 curl_realloc_callback Curl_crealloc;
230 curl_strdup_callback Curl_cstrdup;
231 curl_calloc_callback Curl_ccalloc;
232 #endif
233
234 #if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__)
235 #  pragma warning(default:4232) /* MSVC extension, dllimport identity */
236 #endif
237
238 /**
239  * curl_global_init() globally initializes cURL given a bitwise set of the
240  * different features of what to initialize.
241  */
242 CURLcode curl_global_init(long flags)
243 {
244   if(initialized++)
245     return CURLE_OK;
246
247   /* Setup the default memory functions here (again) */
248   Curl_cmalloc = (curl_malloc_callback)malloc;
249   Curl_cfree = (curl_free_callback)free;
250   Curl_crealloc = (curl_realloc_callback)realloc;
251   Curl_cstrdup = (curl_strdup_callback)system_strdup;
252   Curl_ccalloc = (curl_calloc_callback)calloc;
253
254   if(flags & CURL_GLOBAL_SSL)
255     if(!Curl_ssl_init()) {
256       DEBUGF(fprintf(stderr, "Error: Curl_ssl_init failed\n"));
257       return CURLE_FAILED_INIT;
258     }
259
260   if(flags & CURL_GLOBAL_WIN32)
261     if(win32_init() != CURLE_OK) {
262       DEBUGF(fprintf(stderr, "Error: win32_init failed\n"));
263       return CURLE_FAILED_INIT;
264     }
265
266 #ifdef __AMIGA__
267   if(!amiga_init()) {
268     DEBUGF(fprintf(stderr, "Error: amiga_init failed\n"));
269     return CURLE_FAILED_INIT;
270   }
271 #endif
272
273 #ifdef NETWARE
274   if(netware_init()) {
275     DEBUGF(fprintf(stderr, "Warning: LONG namespace not available\n"));
276   }
277 #endif
278
279 #ifdef USE_LIBIDN
280   idna_init();
281 #endif
282
283 #ifdef CARES_HAVE_ARES_LIBRARY_INIT
284   if(ares_library_init(ARES_LIB_INIT_ALL)) {
285     DEBUGF(fprintf(stderr, "Error: ares_library_init failed\n"));
286     return CURLE_FAILED_INIT;
287   }
288 #endif
289
290 #if defined(USE_LIBSSH2) && defined(HAVE_LIBSSH2_INIT)
291   if(libssh2_init(0)) {
292     DEBUGF(fprintf(stderr, "Error: libssh2_init failed\n"));
293     return CURLE_FAILED_INIT;
294   }
295 #endif
296
297   init_flags  = flags;
298
299   /* Preset pseudo-random number sequence. */
300
301   Curl_srand();
302
303   return CURLE_OK;
304 }
305
306 /*
307  * curl_global_init_mem() globally initializes cURL and also registers the
308  * user provided callback routines.
309  */
310 CURLcode curl_global_init_mem(long flags, curl_malloc_callback m,
311                               curl_free_callback f, curl_realloc_callback r,
312                               curl_strdup_callback s, curl_calloc_callback c)
313 {
314   CURLcode code = CURLE_OK;
315
316   /* Invalid input, return immediately */
317   if(!m || !f || !r || !s || !c)
318     return CURLE_FAILED_INIT;
319
320   /* Already initialized, don't do it again */
321   if( initialized )
322     return CURLE_OK;
323
324   /* Call the actual init function first */
325   code = curl_global_init(flags);
326   if(code == CURLE_OK) {
327     Curl_cmalloc = m;
328     Curl_cfree = f;
329     Curl_cstrdup = s;
330     Curl_crealloc = r;
331     Curl_ccalloc = c;
332   }
333
334   return code;
335 }
336
337 /**
338  * curl_global_cleanup() globally cleanups cURL, uses the value of
339  * "init_flags" to determine what needs to be cleaned up and what doesn't.
340  */
341 void curl_global_cleanup(void)
342 {
343   if(!initialized)
344     return;
345
346   if(--initialized)
347     return;
348
349   Curl_global_host_cache_dtor();
350
351   if(init_flags & CURL_GLOBAL_SSL)
352     Curl_ssl_cleanup();
353
354 #ifdef CARES_HAVE_ARES_LIBRARY_CLEANUP
355   ares_library_cleanup();
356 #endif
357
358   if(init_flags & CURL_GLOBAL_WIN32)
359     win32_cleanup();
360
361 #ifdef __AMIGA__
362   amiga_cleanup();
363 #endif
364
365 #if defined(USE_LIBSSH2) && defined(HAVE_LIBSSH2_EXIT)
366   (void)libssh2_exit();
367 #endif
368
369   init_flags  = 0;
370 }
371
372 /*
373  * curl_easy_init() is the external interface to alloc, setup and init an
374  * easy handle that is returned. If anything goes wrong, NULL is returned.
375  */
376 CURL *curl_easy_init(void)
377 {
378   CURLcode res;
379   struct SessionHandle *data;
380
381   /* Make sure we inited the global SSL stuff */
382   if(!initialized) {
383     res = curl_global_init(CURL_GLOBAL_DEFAULT);
384     if(res) {
385       /* something in the global init failed, return nothing */
386       DEBUGF(fprintf(stderr, "Error: curl_global_init failed\n"));
387       return NULL;
388     }
389   }
390
391   /* We use curl_open() with undefined URL so far */
392   res = Curl_open(&data);
393   if(res != CURLE_OK) {
394     DEBUGF(fprintf(stderr, "Error: Curl_open failed\n"));
395     return NULL;
396   }
397
398   return data;
399 }
400
401 /*
402  * curl_easy_setopt() is the external interface for setting options on an
403  * easy handle.
404  */
405
406 #undef curl_easy_setopt
407 CURLcode curl_easy_setopt(CURL *curl, CURLoption tag, ...)
408 {
409   va_list arg;
410   struct SessionHandle *data = curl;
411   CURLcode ret;
412
413   if(!curl)
414     return CURLE_BAD_FUNCTION_ARGUMENT;
415
416   va_start(arg, tag);
417
418   ret = Curl_setopt(data, tag, arg);
419
420   va_end(arg);
421   return ret;
422 }
423
424 #ifdef CURL_MULTIEASY
425 /***************************************************************************
426  * This function is still only for testing purposes. It makes a great way
427  * to run the full test suite on the multi interface instead of the easy one.
428  ***************************************************************************
429  *
430  * The *new* curl_easy_perform() is the external interface that performs a
431  * transfer previously setup.
432  *
433  * Wrapper-function that: creates a multi handle, adds the easy handle to it,
434  * runs curl_multi_perform() until the transfer is done, then detaches the
435  * easy handle, destroys the multi handle and returns the easy handle's return
436  * code. This will make everything internally use and assume multi interface.
437  */
438 CURLcode curl_easy_perform(CURL *easy)
439 {
440   CURLM *multi;
441   CURLMcode mcode;
442   CURLcode code = CURLE_OK;
443   int still_running;
444   struct timeval timeout;
445   int rc;
446   CURLMsg *msg;
447   fd_set fdread;
448   fd_set fdwrite;
449   fd_set fdexcep;
450   int maxfd;
451
452   if(!easy)
453     return CURLE_BAD_FUNCTION_ARGUMENT;
454
455   multi = curl_multi_init();
456   if(!multi)
457     return CURLE_OUT_OF_MEMORY;
458
459   mcode = curl_multi_add_handle(multi, easy);
460   if(mcode) {
461     curl_multi_cleanup(multi);
462     if(mcode == CURLM_OUT_OF_MEMORY)
463       return CURLE_OUT_OF_MEMORY;
464     else
465       return CURLE_FAILED_INIT;
466   }
467
468   /* we start some action by calling perform right away */
469
470   do {
471     while(CURLM_CALL_MULTI_PERFORM ==
472           curl_multi_perform(multi, &still_running));
473
474     if(!still_running)
475       break;
476
477     FD_ZERO(&fdread);
478     FD_ZERO(&fdwrite);
479     FD_ZERO(&fdexcep);
480
481     /* timeout once per second */
482     timeout.tv_sec = 1;
483     timeout.tv_usec = 0;
484
485     /* Old deprecated style: get file descriptors from the transfers */
486     curl_multi_fdset(multi, &fdread, &fdwrite, &fdexcep, &maxfd);
487     rc = Curl_select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
488
489     /* The way is to extract the sockets and wait for them without using
490        select. This whole alternative version should probably rather use the
491        curl_multi_socket() approach. */
492
493     if(rc == -1)
494       /* select error */
495       break;
496
497     /* timeout or data to send/receive => loop! */
498   } while(still_running);
499
500   msg = curl_multi_info_read(multi, &rc);
501   if(msg)
502     code = msg->data.result;
503
504   mcode = curl_multi_remove_handle(multi, easy);
505   /* what to do if it fails? */
506
507   mcode = curl_multi_cleanup(multi);
508   /* what to do if it fails? */
509
510   return code;
511 }
512 #else
513 /*
514  * curl_easy_perform() is the external interface that performs a transfer
515  * previously setup.
516  */
517 CURLcode curl_easy_perform(CURL *curl)
518 {
519   struct SessionHandle *data = (struct SessionHandle *)curl;
520
521   if(!data)
522     return CURLE_BAD_FUNCTION_ARGUMENT;
523
524   if( ! (data->share && data->share->hostcache) ) {
525     /* this handle is not using a shared dns cache */
526
527     if(data->set.global_dns_cache &&
528        (data->dns.hostcachetype != HCACHE_GLOBAL)) {
529       /* global dns cache was requested but still isn't */
530       struct curl_hash *ptr;
531
532       if(data->dns.hostcachetype == HCACHE_PRIVATE) {
533         /* if the current cache is private, kill it first */
534         Curl_hash_destroy(data->dns.hostcache);
535         data->dns.hostcachetype = HCACHE_NONE;
536         data->dns.hostcache = NULL;
537       }
538
539       ptr = Curl_global_host_cache_init();
540       if(ptr) {
541         /* only do this if the global cache init works */
542         data->dns.hostcache = ptr;
543         data->dns.hostcachetype = HCACHE_GLOBAL;
544       }
545     }
546
547     if(!data->dns.hostcache) {
548       data->dns.hostcachetype = HCACHE_PRIVATE;
549       data->dns.hostcache = Curl_mk_dnscache();
550
551       if(!data->dns.hostcache)
552         /* While we possibly could survive and do good without a host cache,
553            the fact that creating it failed indicates that things are truly
554            screwed up and we should bail out! */
555         return CURLE_OUT_OF_MEMORY;
556     }
557
558   }
559
560   if(!data->state.connc) {
561     /* oops, no connection cache, make one up */
562     data->state.connc = Curl_mk_connc(CONNCACHE_PRIVATE, -1L);
563     if(!data->state.connc)
564       return CURLE_OUT_OF_MEMORY;
565   }
566
567   return Curl_perform(data);
568 }
569 #endif
570
571 /*
572  * curl_easy_cleanup() is the external interface to cleaning/freeing the given
573  * easy handle.
574  */
575 void curl_easy_cleanup(CURL *curl)
576 {
577   struct SessionHandle *data = (struct SessionHandle *)curl;
578
579   if(!data)
580     return;
581
582   Curl_close(data);
583 }
584
585 /*
586  * Store a pointed to the multi handle within the easy handle's data struct.
587  */
588 void Curl_easy_addmulti(struct SessionHandle *data,
589                         void *multi)
590 {
591   data->multi = multi;
592   if(multi == NULL)
593     /* the association is cleared, mark the easy handle as not used by an
594        interface */
595     data->state.used_interface = Curl_if_none;
596 }
597
598 void Curl_easy_initHandleData(struct SessionHandle *data)
599 {
600     memset(&data->req, 0, sizeof(struct SingleRequest));
601
602     data->req.maxdownload = -1;
603 }
604
605 /*
606  * curl_easy_getinfo() is an external interface that allows an app to retrieve
607  * information from a performed transfer and similar.
608  */
609 #undef curl_easy_getinfo
610 CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...)
611 {
612   va_list arg;
613   void *paramp;
614   struct SessionHandle *data = (struct SessionHandle *)curl;
615
616   va_start(arg, info);
617   paramp = va_arg(arg, void *);
618
619   return Curl_getinfo(data, info, paramp);
620 }
621
622 /*
623  * curl_easy_duphandle() is an external interface to allow duplication of a
624  * given input easy handle. The returned handle will be a new working handle
625  * with all options set exactly as the input source handle.
626  */
627 CURL *curl_easy_duphandle(CURL *incurl)
628 {
629   struct SessionHandle *data=(struct SessionHandle *)incurl;
630
631   struct SessionHandle *outcurl = calloc(1, sizeof(struct SessionHandle));
632   if(NULL == outcurl)
633     goto fail;
634
635   /*
636    * We setup a few buffers we need. We should probably make them
637    * get setup on-demand in the code, as that would probably decrease
638    * the likeliness of us forgetting to init a buffer here in the future.
639    */
640   outcurl->state.headerbuff = malloc(HEADERSIZE);
641   if(!outcurl->state.headerbuff)
642     goto fail;
643   outcurl->state.headersize = HEADERSIZE;
644
645   /* copy all userdefined values */
646   if(Curl_dupset(outcurl, data) != CURLE_OK)
647     goto fail;
648
649   /* the connection cache is setup on demand */
650   outcurl->state.connc = NULL;
651
652   outcurl->state.lastconnect = -1;
653
654   outcurl->progress.flags    = data->progress.flags;
655   outcurl->progress.callback = data->progress.callback;
656
657 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
658   if(data->cookies) {
659     /* If cookies are enabled in the parent handle, we enable them
660        in the clone as well! */
661     outcurl->cookies = Curl_cookie_init(data,
662                                         data->cookies->filename,
663                                         outcurl->cookies,
664                                         data->set.cookiesession);
665     if(!outcurl->cookies)
666       goto fail;
667   }
668 #endif   /* CURL_DISABLE_HTTP */
669
670   /* duplicate all values in 'change' */
671
672 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
673   if(data->change.cookielist) {
674     outcurl->change.cookielist =
675       Curl_slist_duplicate(data->change.cookielist);
676     if(!outcurl->change.cookielist)
677       goto fail;
678   }
679 #endif   /* CURL_DISABLE_HTTP */
680
681   if(data->change.url) {
682     outcurl->change.url = strdup(data->change.url);
683     if(!outcurl->change.url)
684       goto fail;
685     outcurl->change.url_alloc = TRUE;
686   }
687
688   if(data->change.referer) {
689     outcurl->change.referer = strdup(data->change.referer);
690     if(!outcurl->change.referer)
691       goto fail;
692     outcurl->change.referer_alloc = TRUE;
693   }
694
695 #ifdef USE_ARES
696   /* If we use ares, we clone the ares channel for the new handle */
697   if(ARES_SUCCESS != ares_dup(&outcurl->state.areschannel,
698                               data->state.areschannel))
699     goto fail;
700 #endif
701
702 #if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
703   outcurl->inbound_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
704                                    CURL_ICONV_CODESET_OF_NETWORK);
705   outcurl->outbound_cd = iconv_open(CURL_ICONV_CODESET_OF_NETWORK,
706                                     CURL_ICONV_CODESET_OF_HOST);
707   outcurl->utf8_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
708                                 CURL_ICONV_CODESET_FOR_UTF8);
709 #endif
710
711   Curl_easy_initHandleData(outcurl);
712
713   outcurl->magic = CURLEASY_MAGIC_NUMBER;
714
715   /* we reach this point and thus we are OK */
716
717   return outcurl;
718
719   fail:
720
721   if(outcurl) {
722     if(outcurl->state.connc &&
723        (outcurl->state.connc->type == CONNCACHE_PRIVATE))
724       Curl_rm_connc(outcurl->state.connc);
725     if(outcurl->state.headerbuff)
726       free(outcurl->state.headerbuff);
727 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
728     if(outcurl->change.cookielist)
729       curl_slist_free_all(outcurl->change.cookielist);
730 #endif
731     if(outcurl->change.url)
732       free(outcurl->change.url);
733     if(outcurl->change.referer)
734       free(outcurl->change.referer);
735     Curl_freeset(outcurl);
736     free(outcurl);
737   }
738
739   return NULL;
740 }
741
742 /*
743  * curl_easy_reset() is an external interface that allows an app to re-
744  * initialize a session handle to the default values.
745  */
746 void curl_easy_reset(CURL *curl)
747 {
748   struct SessionHandle *data = (struct SessionHandle *)curl;
749
750   Curl_safefree(data->state.pathbuffer);
751   data->state.pathbuffer=NULL;
752
753   Curl_safefree(data->state.proto.generic);
754   data->state.proto.generic=NULL;
755
756   /* zero out UserDefined data: */
757   Curl_freeset(data);
758   memset(&data->set, 0, sizeof(struct UserDefined));
759   (void)Curl_init_userdefined(&data->set);
760
761   /* zero out Progress data: */
762   memset(&data->progress, 0, sizeof(struct Progress));
763
764   /* init Handle data */
765   Curl_easy_initHandleData(data);
766
767   data->progress.flags |= PGRS_HIDE;
768   data->state.current_speed = -1; /* init to negative == impossible */
769 }
770
771 /*
772  * curl_easy_pause() allows an application to pause or unpause a specific
773  * transfer and direction. This function sets the full new state for the
774  * current connection this easy handle operates on.
775  *
776  * NOTE: if you have the receiving paused and you call this function to remove
777  * the pausing, you may get your write callback called at this point.
778  *
779  * Action is a bitmask consisting of CURLPAUSE_* bits in curl/curl.h
780  */
781 CURLcode curl_easy_pause(CURL *curl, int action)
782 {
783   struct SessionHandle *data = (struct SessionHandle *)curl;
784   struct SingleRequest *k = &data->req;
785   CURLcode result = CURLE_OK;
786
787   /* first switch off both pause bits */
788   int newstate = k->keepon &~ (KEEP_RECV_PAUSE| KEEP_SEND_PAUSE);
789
790   /* set the new desired pause bits */
791   newstate |= ((action & CURLPAUSE_RECV)?KEEP_RECV_PAUSE:0) |
792     ((action & CURLPAUSE_SEND)?KEEP_SEND_PAUSE:0);
793
794   /* put it back in the keepon */
795   k->keepon = newstate;
796
797   if(!(newstate & KEEP_RECV_PAUSE) && data->state.tempwrite) {
798     /* we have a buffer for sending that we now seem to be able to deliver since
799        the receive pausing is lifted! */
800
801     /* get the pointer, type and length in local copies since the function may
802        return PAUSE again and then we'll get a new copy allocted and stored in
803        the tempwrite variables */
804     char *tempwrite = data->state.tempwrite;
805     char *freewrite = tempwrite; /* store this pointer to free it later */
806     size_t tempsize = data->state.tempwritesize;
807     int temptype = data->state.tempwritetype;
808     size_t chunklen;
809
810     /* clear tempwrite here just to make sure it gets cleared if there's no
811        further use of it, and make sure we don't clear it after the function
812        invoke as it may have been set to a new value by then */
813     data->state.tempwrite = NULL;
814
815     /* since the write callback API is define to never exceed
816        CURL_MAX_WRITE_SIZE bytes in a single call, and since we may in fact
817        have more data than that in our buffer here, we must loop sending the
818        data in multiple calls until there's no data left or we get another
819        pause returned.
820
821        A tricky part is that the function we call will "buffer" the data
822        itself when it pauses on a particular buffer, so we may need to do some
823        extra trickery if we get a pause return here.
824     */
825     do {
826       chunklen = (tempsize > CURL_MAX_WRITE_SIZE)?CURL_MAX_WRITE_SIZE:tempsize;
827
828       result = Curl_client_write(data->state.current_conn,
829                                  temptype, tempwrite, chunklen);
830       if(result)
831         /* failures abort the loop at once */
832         break;
833
834       if(data->state.tempwrite && (tempsize - chunklen)) {
835         /* Ouch, the reading is again paused and the block we send is now
836            "cached". If this is the final chunk we can leave it like this, but
837            if we have more chunks that are cached after this, we need to free
838            the newly cached one and put back a version that is truly the entire
839            contents that is saved for later
840         */
841         char *newptr;
842
843         /* note that tempsize is still the size as before the callback was
844            used, and thus the whole piece of data to keep */
845         newptr = realloc(data->state.tempwrite, tempsize);
846
847         if(!newptr) {
848           free(data->state.tempwrite); /* free old area */
849           data->state.tempwrite = NULL;
850           result = CURLE_OUT_OF_MEMORY;
851           /* tempwrite will be freed further down */
852           break;
853         }
854         data->state.tempwrite = newptr; /* store new pointer */
855         memcpy(newptr, tempwrite, tempsize);
856         data->state.tempwritesize = tempsize; /* store new size */
857         /* tempwrite will be freed further down */
858         break; /* go back to pausing until further notice */
859       }
860       else {
861         tempsize -= chunklen;  /* left after the call above */
862         tempwrite += chunklen; /* advance the pointer */
863       }
864
865     } while((result == CURLE_OK) && tempsize);
866
867     free(freewrite); /* this is unconditionally no longer used */
868   }
869
870   return result;
871 }
872
873 #ifdef CURL_DOES_CONVERSIONS
874 /*
875  * Curl_convert_to_network() is an internal function
876  * for performing ASCII conversions on non-ASCII platforms.
877  */
878 CURLcode Curl_convert_to_network(struct SessionHandle *data,
879                                  char *buffer, size_t length)
880 {
881   CURLcode rc;
882
883   if(data->set.convtonetwork) {
884     /* use translation callback */
885     rc = data->set.convtonetwork(buffer, length);
886     if(rc != CURLE_OK) {
887       failf(data,
888             "CURLOPT_CONV_TO_NETWORK_FUNCTION callback returned %d: %s",
889             (int)rc, curl_easy_strerror(rc));
890     }
891     return(rc);
892   }
893   else {
894 #ifdef HAVE_ICONV
895     /* do the translation ourselves */
896     char *input_ptr, *output_ptr;
897     size_t in_bytes, out_bytes, rc;
898     int error;
899
900     /* open an iconv conversion descriptor if necessary */
901     if(data->outbound_cd == (iconv_t)-1) {
902       data->outbound_cd = iconv_open(CURL_ICONV_CODESET_OF_NETWORK,
903                                      CURL_ICONV_CODESET_OF_HOST);
904       if(data->outbound_cd == (iconv_t)-1) {
905         error = ERRNO;
906         failf(data,
907               "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
908                CURL_ICONV_CODESET_OF_NETWORK,
909                CURL_ICONV_CODESET_OF_HOST,
910                error, strerror(error));
911         return CURLE_CONV_FAILED;
912       }
913     }
914     /* call iconv */
915     input_ptr = output_ptr = buffer;
916     in_bytes = out_bytes = length;
917     rc = iconv(data->outbound_cd, (const char**)&input_ptr, &in_bytes,
918                &output_ptr, &out_bytes);
919     if((rc == ICONV_ERROR) || (in_bytes != 0)) {
920       error = ERRNO;
921       failf(data,
922         "The Curl_convert_to_network iconv call failed with errno %i: %s",
923              error, strerror(error));
924       return CURLE_CONV_FAILED;
925     }
926 #else
927     failf(data, "CURLOPT_CONV_TO_NETWORK_FUNCTION callback required");
928     return CURLE_CONV_REQD;
929 #endif /* HAVE_ICONV */
930   }
931
932   return CURLE_OK;
933 }
934
935 /*
936  * Curl_convert_from_network() is an internal function
937  * for performing ASCII conversions on non-ASCII platforms.
938  */
939 CURLcode Curl_convert_from_network(struct SessionHandle *data,
940                                       char *buffer, size_t length)
941 {
942   CURLcode rc;
943
944   if(data->set.convfromnetwork) {
945     /* use translation callback */
946     rc = data->set.convfromnetwork(buffer, length);
947     if(rc != CURLE_OK) {
948       failf(data,
949             "CURLOPT_CONV_FROM_NETWORK_FUNCTION callback returned %d: %s",
950             (int)rc, curl_easy_strerror(rc));
951     }
952     return(rc);
953   }
954   else {
955 #ifdef HAVE_ICONV
956     /* do the translation ourselves */
957     char *input_ptr, *output_ptr;
958     size_t in_bytes, out_bytes, rc;
959     int error;
960
961     /* open an iconv conversion descriptor if necessary */
962     if(data->inbound_cd == (iconv_t)-1) {
963       data->inbound_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
964                                     CURL_ICONV_CODESET_OF_NETWORK);
965       if(data->inbound_cd == (iconv_t)-1) {
966         error = ERRNO;
967         failf(data,
968               "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
969               CURL_ICONV_CODESET_OF_HOST,
970               CURL_ICONV_CODESET_OF_NETWORK,
971               error, strerror(error));
972         return CURLE_CONV_FAILED;
973       }
974     }
975     /* call iconv */
976     input_ptr = output_ptr = buffer;
977     in_bytes = out_bytes = length;
978     rc = iconv(data->inbound_cd, (const char **)&input_ptr, &in_bytes,
979                &output_ptr, &out_bytes);
980     if((rc == ICONV_ERROR) || (in_bytes != 0)) {
981       error = ERRNO;
982       failf(data,
983             "The Curl_convert_from_network iconv call failed with errno %i: %s",
984             error, strerror(error));
985       return CURLE_CONV_FAILED;
986     }
987 #else
988     failf(data, "CURLOPT_CONV_FROM_NETWORK_FUNCTION callback required");
989     return CURLE_CONV_REQD;
990 #endif /* HAVE_ICONV */
991   }
992
993   return CURLE_OK;
994 }
995
996 /*
997  * Curl_convert_from_utf8() is an internal function
998  * for performing UTF-8 conversions on non-ASCII platforms.
999  */
1000 CURLcode Curl_convert_from_utf8(struct SessionHandle *data,
1001                                      char *buffer, size_t length)
1002 {
1003   CURLcode rc;
1004
1005   if(data->set.convfromutf8) {
1006     /* use translation callback */
1007     rc = data->set.convfromutf8(buffer, length);
1008     if(rc != CURLE_OK) {
1009       failf(data,
1010             "CURLOPT_CONV_FROM_UTF8_FUNCTION callback returned %d: %s",
1011             (int)rc, curl_easy_strerror(rc));
1012     }
1013     return(rc);
1014   }
1015   else {
1016 #ifdef HAVE_ICONV
1017     /* do the translation ourselves */
1018     const char *input_ptr;
1019     char *output_ptr;
1020     size_t in_bytes, out_bytes, rc;
1021     int error;
1022
1023     /* open an iconv conversion descriptor if necessary */
1024     if(data->utf8_cd == (iconv_t)-1) {
1025       data->utf8_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
1026                                  CURL_ICONV_CODESET_FOR_UTF8);
1027       if(data->utf8_cd == (iconv_t)-1) {
1028         error = ERRNO;
1029         failf(data,
1030               "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
1031               CURL_ICONV_CODESET_OF_HOST,
1032               CURL_ICONV_CODESET_FOR_UTF8,
1033               error, strerror(error));
1034         return CURLE_CONV_FAILED;
1035       }
1036     }
1037     /* call iconv */
1038     input_ptr = output_ptr = buffer;
1039     in_bytes = out_bytes = length;
1040     rc = iconv(data->utf8_cd, &input_ptr, &in_bytes,
1041                &output_ptr, &out_bytes);
1042     if((rc == ICONV_ERROR) || (in_bytes != 0)) {
1043       error = ERRNO;
1044       failf(data,
1045             "The Curl_convert_from_utf8 iconv call failed with errno %i: %s",
1046             error, strerror(error));
1047       return CURLE_CONV_FAILED;
1048     }
1049     if(output_ptr < input_ptr) {
1050       /* null terminate the now shorter output string */
1051       *output_ptr = 0x00;
1052     }
1053 #else
1054     failf(data, "CURLOPT_CONV_FROM_UTF8_FUNCTION callback required");
1055     return CURLE_CONV_REQD;
1056 #endif /* HAVE_ICONV */
1057   }
1058
1059   return CURLE_OK;
1060 }
1061
1062 #endif /* CURL_DOES_CONVERSIONS */
1063
1064 static CURLcode easy_connection(struct SessionHandle *data,
1065                                 curl_socket_t *sfd,
1066                                 struct connectdata **connp)
1067 {
1068   if(data == NULL)
1069     return CURLE_BAD_FUNCTION_ARGUMENT;
1070
1071   /* only allow these to be called on handles with CURLOPT_CONNECT_ONLY */
1072   if(!data->set.connect_only) {
1073     failf(data, "CONNECT_ONLY is required!");
1074     return CURLE_UNSUPPORTED_PROTOCOL;
1075   }
1076
1077   *sfd = Curl_getconnectinfo(data, connp);
1078
1079   if(*sfd == CURL_SOCKET_BAD) {
1080     failf(data, "Failed to get recent socket");
1081     return CURLE_UNSUPPORTED_PROTOCOL;
1082   }
1083
1084   return CURLE_OK;
1085 }
1086
1087 /*
1088  * Receives data from the connected socket. Use after successful
1089  * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
1090  * Returns CURLE_OK on success, error code on error.
1091  */
1092 CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen, size_t *n)
1093 {
1094   curl_socket_t sfd;
1095   CURLcode ret;
1096   ssize_t n1;
1097   struct connectdata *c;
1098   struct SessionHandle *data = (struct SessionHandle *)curl;
1099
1100   ret = easy_connection(data, &sfd, &c);
1101   if(ret)
1102     return ret;
1103
1104   *n = 0;
1105   ret = Curl_read(c, sfd, buffer, buflen, &n1);
1106
1107   if(ret != CURLE_OK)
1108     return ret;
1109
1110   *n = (size_t)n1;
1111
1112   return CURLE_OK;
1113 }
1114
1115 /*
1116  * Sends data over the connected socket. Use after successful
1117  * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
1118  */
1119 CURLcode curl_easy_send(CURL *curl, const void *buffer, size_t buflen,
1120                         size_t *n)
1121 {
1122   curl_socket_t sfd;
1123   CURLcode ret;
1124   ssize_t n1;
1125   struct connectdata *c = NULL;
1126   struct SessionHandle *data = (struct SessionHandle *)curl;
1127
1128   ret = easy_connection(data, &sfd, &c);
1129   if(ret)
1130     return ret;
1131
1132   *n = 0;
1133   ret = Curl_write(c, sfd, buffer, buflen, &n1);
1134
1135   if(n1 == -1)
1136     return CURLE_SEND_ERROR;
1137
1138   /* detect EAGAIN */
1139   if((CURLE_OK == ret) && (0 == n1))
1140     return CURLE_AGAIN;
1141
1142   *n = (size_t)n1;
1143
1144   return ret;
1145 }