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