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