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