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