• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2016, 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 https://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 #include "urldata.h"
54 #include <curl/curl.h>
55 #include "transfer.h"
56 #include "vtls/vtls.h"
57 #include "url.h"
58 #include "getinfo.h"
59 #include "hostip.h"
60 #include "share.h"
61 #include "strdup.h"
62 #include "progress.h"
63 #include "easyif.h"
64 #include "select.h"
65 #include "sendf.h" /* for failf function prototype */
66 #include "connect.h" /* for Curl_getconnectinfo */
67 #include "slist.h"
68 #include "amigaos.h"
69 #include "non-ascii.h"
70 #include "warnless.h"
71 #include "conncache.h"
72 #include "multiif.h"
73 #include "sigpipe.h"
74 #include "ssh.h"
75 /* The last 3 #include files should be in this order */
76 #include "curl_printf.h"
77 #include "curl_memory.h"
78 #include "memdebug.h"
79 
80 void Curl_version_init(void);
81 
82 /* win32_cleanup() is for win32 socket cleanup functionality, the opposite
83    of win32_init() */
win32_cleanup(void)84 static void win32_cleanup(void)
85 {
86 #ifdef USE_WINSOCK
87   WSACleanup();
88 #endif
89 #ifdef USE_WINDOWS_SSPI
90   Curl_sspi_global_cleanup();
91 #endif
92 }
93 
94 /* win32_init() performs win32 socket initialization to properly setup the
95    stack to allow networking */
win32_init(void)96 static CURLcode win32_init(void)
97 {
98 #ifdef USE_WINSOCK
99   WORD wVersionRequested;
100   WSADATA wsaData;
101   int res;
102 
103 #if defined(ENABLE_IPV6) && (USE_WINSOCK < 2)
104   Error IPV6_requires_winsock2
105 #endif
106 
107   wVersionRequested = MAKEWORD(USE_WINSOCK, USE_WINSOCK);
108 
109   res = WSAStartup(wVersionRequested, &wsaData);
110 
111   if(res != 0)
112     /* Tell the user that we couldn't find a useable */
113     /* winsock.dll.     */
114     return CURLE_FAILED_INIT;
115 
116   /* Confirm that the Windows Sockets DLL supports what we need.*/
117   /* Note that if the DLL supports versions greater */
118   /* than wVersionRequested, it will still return */
119   /* wVersionRequested in wVersion. wHighVersion contains the */
120   /* highest supported version. */
121 
122   if(LOBYTE(wsaData.wVersion) != LOBYTE(wVersionRequested) ||
123      HIBYTE(wsaData.wVersion) != HIBYTE(wVersionRequested) ) {
124     /* Tell the user that we couldn't find a useable */
125 
126     /* winsock.dll. */
127     WSACleanup();
128     return CURLE_FAILED_INIT;
129   }
130   /* The Windows Sockets DLL is acceptable. Proceed. */
131 #elif defined(USE_LWIPSOCK)
132   lwip_init();
133 #endif
134 
135 #ifdef USE_WINDOWS_SSPI
136   {
137     CURLcode result = Curl_sspi_global_init();
138     if(result)
139       return result;
140   }
141 #endif
142 
143   return CURLE_OK;
144 }
145 
146 /* true globals -- for curl_global_init() and curl_global_cleanup() */
147 static unsigned int  initialized;
148 static long          init_flags;
149 
150 /*
151  * strdup (and other memory functions) is redefined in complicated
152  * ways, but at this point it must be defined as the system-supplied strdup
153  * so the callback pointer is initialized correctly.
154  */
155 #if defined(_WIN32_WCE)
156 #define system_strdup _strdup
157 #elif !defined(HAVE_STRDUP)
158 #define system_strdup curlx_strdup
159 #else
160 #define system_strdup strdup
161 #endif
162 
163 #if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__)
164 #  pragma warning(disable:4232) /* MSVC extension, dllimport identity */
165 #endif
166 
167 #ifndef __SYMBIAN32__
168 /*
169  * If a memory-using function (like curl_getenv) is used before
170  * curl_global_init() is called, we need to have these pointers set already.
171  */
172 curl_malloc_callback Curl_cmalloc = (curl_malloc_callback)malloc;
173 curl_free_callback Curl_cfree = (curl_free_callback)free;
174 curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc;
175 curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)system_strdup;
176 curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc;
177 #if defined(WIN32) && defined(UNICODE)
178 curl_wcsdup_callback Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup;
179 #endif
180 #else
181 /*
182  * Symbian OS doesn't support initialization to code in writeable static data.
183  * Initialization will occur in the curl_global_init() call.
184  */
185 curl_malloc_callback Curl_cmalloc;
186 curl_free_callback Curl_cfree;
187 curl_realloc_callback Curl_crealloc;
188 curl_strdup_callback Curl_cstrdup;
189 curl_calloc_callback Curl_ccalloc;
190 #endif
191 
192 #if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__)
193 #  pragma warning(default:4232) /* MSVC extension, dllimport identity */
194 #endif
195 
196 /**
197  * curl_global_init() globally initializes curl given a bitwise set of the
198  * different features of what to initialize.
199  */
global_init(long flags,bool memoryfuncs)200 static CURLcode global_init(long flags, bool memoryfuncs)
201 {
202   if(initialized++)
203     return CURLE_OK;
204 
205   if(memoryfuncs) {
206     /* Setup the default memory functions here (again) */
207     Curl_cmalloc = (curl_malloc_callback)malloc;
208     Curl_cfree = (curl_free_callback)free;
209     Curl_crealloc = (curl_realloc_callback)realloc;
210     Curl_cstrdup = (curl_strdup_callback)system_strdup;
211     Curl_ccalloc = (curl_calloc_callback)calloc;
212 #if defined(WIN32) && defined(UNICODE)
213     Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup;
214 #endif
215   }
216 
217   if(flags & CURL_GLOBAL_SSL)
218     if(!Curl_ssl_init()) {
219       DEBUGF(fprintf(stderr, "Error: Curl_ssl_init failed\n"));
220       return CURLE_FAILED_INIT;
221     }
222 
223   if(flags & CURL_GLOBAL_WIN32)
224     if(win32_init()) {
225       DEBUGF(fprintf(stderr, "Error: win32_init failed\n"));
226       return CURLE_FAILED_INIT;
227     }
228 
229 #ifdef __AMIGA__
230   if(!Curl_amiga_init()) {
231     DEBUGF(fprintf(stderr, "Error: Curl_amiga_init failed\n"));
232     return CURLE_FAILED_INIT;
233   }
234 #endif
235 
236 #ifdef NETWARE
237   if(netware_init()) {
238     DEBUGF(fprintf(stderr, "Warning: LONG namespace not available\n"));
239   }
240 #endif
241 
242   if(Curl_resolver_global_init()) {
243     DEBUGF(fprintf(stderr, "Error: resolver_global_init failed\n"));
244     return CURLE_FAILED_INIT;
245   }
246 
247   (void)Curl_ipv6works();
248 
249 #if defined(USE_LIBSSH2) && defined(HAVE_LIBSSH2_INIT)
250   if(libssh2_init(0)) {
251     DEBUGF(fprintf(stderr, "Error: libssh2_init failed\n"));
252     return CURLE_FAILED_INIT;
253   }
254 #endif
255 
256   if(flags & CURL_GLOBAL_ACK_EINTR)
257     Curl_ack_eintr = 1;
258 
259   init_flags = flags;
260 
261   Curl_version_init();
262 
263   return CURLE_OK;
264 }
265 
266 
267 /**
268  * curl_global_init() globally initializes curl given a bitwise set of the
269  * different features of what to initialize.
270  */
curl_global_init(long flags)271 CURLcode curl_global_init(long flags)
272 {
273   return global_init(flags, TRUE);
274 }
275 
276 /*
277  * curl_global_init_mem() globally initializes curl and also registers the
278  * user provided callback routines.
279  */
curl_global_init_mem(long flags,curl_malloc_callback m,curl_free_callback f,curl_realloc_callback r,curl_strdup_callback s,curl_calloc_callback c)280 CURLcode curl_global_init_mem(long flags, curl_malloc_callback m,
281                               curl_free_callback f, curl_realloc_callback r,
282                               curl_strdup_callback s, curl_calloc_callback c)
283 {
284   /* Invalid input, return immediately */
285   if(!m || !f || !r || !s || !c)
286     return CURLE_FAILED_INIT;
287 
288   if(initialized) {
289     /* Already initialized, don't do it again, but bump the variable anyway to
290        work like curl_global_init() and require the same amount of cleanup
291        calls. */
292     initialized++;
293     return CURLE_OK;
294   }
295 
296   /* set memory functions before global_init() in case it wants memory
297      functions */
298   Curl_cmalloc = m;
299   Curl_cfree = f;
300   Curl_cstrdup = s;
301   Curl_crealloc = r;
302   Curl_ccalloc = c;
303 
304   /* Call the actual init function, but without setting */
305   return global_init(flags, FALSE);
306 }
307 
308 /**
309  * curl_global_cleanup() globally cleanups curl, uses the value of
310  * "init_flags" to determine what needs to be cleaned up and what doesn't.
311  */
curl_global_cleanup(void)312 void curl_global_cleanup(void)
313 {
314   if(!initialized)
315     return;
316 
317   if(--initialized)
318     return;
319 
320   Curl_global_host_cache_dtor();
321 
322   if(init_flags & CURL_GLOBAL_SSL)
323     Curl_ssl_cleanup();
324 
325   Curl_resolver_global_cleanup();
326 
327   if(init_flags & CURL_GLOBAL_WIN32)
328     win32_cleanup();
329 
330   Curl_amiga_cleanup();
331 
332 #if defined(USE_LIBSSH2) && defined(HAVE_LIBSSH2_EXIT)
333   (void)libssh2_exit();
334 #endif
335 
336   init_flags  = 0;
337 }
338 
339 /*
340  * curl_easy_init() is the external interface to alloc, setup and init an
341  * easy handle that is returned. If anything goes wrong, NULL is returned.
342  */
curl_easy_init(void)343 struct Curl_easy *curl_easy_init(void)
344 {
345   CURLcode result;
346   struct Curl_easy *data;
347 
348   /* Make sure we inited the global SSL stuff */
349   if(!initialized) {
350     result = curl_global_init(CURL_GLOBAL_DEFAULT);
351     if(result) {
352       /* something in the global init failed, return nothing */
353       DEBUGF(fprintf(stderr, "Error: curl_global_init failed\n"));
354       return NULL;
355     }
356   }
357 
358   /* We use curl_open() with undefined URL so far */
359   result = Curl_open(&data);
360   if(result) {
361     DEBUGF(fprintf(stderr, "Error: Curl_open failed\n"));
362     return NULL;
363   }
364 
365   return data;
366 }
367 
368 /*
369  * curl_easy_setopt() is the external interface for setting options on an
370  * easy handle.
371  */
372 
373 #undef curl_easy_setopt
curl_easy_setopt(struct Curl_easy * data,CURLoption tag,...)374 CURLcode curl_easy_setopt(struct Curl_easy *data, CURLoption tag, ...)
375 {
376   va_list arg;
377   CURLcode result;
378 
379   if(!data)
380     return CURLE_BAD_FUNCTION_ARGUMENT;
381 
382   va_start(arg, tag);
383 
384   result = Curl_setopt(data, tag, arg);
385 
386   va_end(arg);
387   return result;
388 }
389 
390 #ifdef CURLDEBUG
391 
392 struct socketmonitor {
393   struct socketmonitor *next; /* the next node in the list or NULL */
394   struct pollfd socket; /* socket info of what to monitor */
395 };
396 
397 struct events {
398   long ms;              /* timeout, run the timeout function when reached */
399   bool msbump;          /* set TRUE when timeout is set by callback */
400   int num_sockets;      /* number of nodes in the monitor list */
401   struct socketmonitor *list; /* list of sockets to monitor */
402   int running_handles;  /* store the returned number */
403 };
404 
405 /* events_timer
406  *
407  * Callback that gets called with a new value when the timeout should be
408  * updated.
409  */
410 
events_timer(struct Curl_multi * multi,long timeout_ms,void * userp)411 static int events_timer(struct Curl_multi *multi,    /* multi handle */
412                         long timeout_ms, /* see above */
413                         void *userp)    /* private callback pointer */
414 {
415   struct events *ev = userp;
416   (void)multi;
417   if(timeout_ms == -1)
418     /* timeout removed */
419     timeout_ms = 0;
420   else if(timeout_ms == 0)
421     /* timeout is already reached! */
422     timeout_ms = 1; /* trigger asap */
423 
424   ev->ms = timeout_ms;
425   ev->msbump = TRUE;
426   return 0;
427 }
428 
429 
430 /* poll2cselect
431  *
432  * convert from poll() bit definitions to libcurl's CURL_CSELECT_* ones
433  */
poll2cselect(int pollmask)434 static int poll2cselect(int pollmask)
435 {
436   int omask=0;
437   if(pollmask & POLLIN)
438     omask |= CURL_CSELECT_IN;
439   if(pollmask & POLLOUT)
440     omask |= CURL_CSELECT_OUT;
441   if(pollmask & POLLERR)
442     omask |= CURL_CSELECT_ERR;
443   return omask;
444 }
445 
446 
447 /* socketcb2poll
448  *
449  * convert from libcurl' CURL_POLL_* bit definitions to poll()'s
450  */
socketcb2poll(int pollmask)451 static short socketcb2poll(int pollmask)
452 {
453   short omask=0;
454   if(pollmask & CURL_POLL_IN)
455     omask |= POLLIN;
456   if(pollmask & CURL_POLL_OUT)
457     omask |= POLLOUT;
458   return omask;
459 }
460 
461 /* events_socket
462  *
463  * Callback that gets called with information about socket activity to
464  * monitor.
465  */
events_socket(struct Curl_easy * easy,curl_socket_t s,int what,void * userp,void * socketp)466 static int events_socket(struct Curl_easy *easy,      /* easy handle */
467                          curl_socket_t s, /* socket */
468                          int what,        /* see above */
469                          void *userp,     /* private callback
470                                              pointer */
471                          void *socketp)   /* private socket
472                                              pointer */
473 {
474   struct events *ev = userp;
475   struct socketmonitor *m;
476   struct socketmonitor *prev=NULL;
477 
478 #if defined(CURL_DISABLE_VERBOSE_STRINGS)
479   (void) easy;
480 #endif
481   (void)socketp;
482 
483   m = ev->list;
484   while(m) {
485     if(m->socket.fd == s) {
486 
487       if(what == CURL_POLL_REMOVE) {
488         struct socketmonitor *nxt = m->next;
489         /* remove this node from the list of monitored sockets */
490         if(prev)
491           prev->next = nxt;
492         else
493           ev->list = nxt;
494         free(m);
495         m = nxt;
496         infof(easy, "socket cb: socket %d REMOVED\n", s);
497       }
498       else {
499         /* The socket 's' is already being monitored, update the activity
500            mask. Convert from libcurl bitmask to the poll one. */
501         m->socket.events = socketcb2poll(what);
502         infof(easy, "socket cb: socket %d UPDATED as %s%s\n", s,
503               what&CURL_POLL_IN?"IN":"",
504               what&CURL_POLL_OUT?"OUT":"");
505       }
506       break;
507     }
508     prev = m;
509     m = m->next; /* move to next node */
510   }
511   if(!m) {
512     if(what == CURL_POLL_REMOVE) {
513       /* this happens a bit too often, libcurl fix perhaps? */
514       /* fprintf(stderr,
515          "%s: socket %d asked to be REMOVED but not present!\n",
516                  __func__, s); */
517     }
518     else {
519       m = malloc(sizeof(struct socketmonitor));
520       if(m) {
521         m->next = ev->list;
522         m->socket.fd = s;
523         m->socket.events = socketcb2poll(what);
524         m->socket.revents = 0;
525         ev->list = m;
526         infof(easy, "socket cb: socket %d ADDED as %s%s\n", s,
527               what&CURL_POLL_IN?"IN":"",
528               what&CURL_POLL_OUT?"OUT":"");
529       }
530       else
531         return CURLE_OUT_OF_MEMORY;
532     }
533   }
534 
535   return 0;
536 }
537 
538 
539 /*
540  * events_setup()
541  *
542  * Do the multi handle setups that only event-based transfers need.
543  */
events_setup(struct Curl_multi * multi,struct events * ev)544 static void events_setup(struct Curl_multi *multi, struct events *ev)
545 {
546   /* timer callback */
547   curl_multi_setopt(multi, CURLMOPT_TIMERFUNCTION, events_timer);
548   curl_multi_setopt(multi, CURLMOPT_TIMERDATA, ev);
549 
550   /* socket callback */
551   curl_multi_setopt(multi, CURLMOPT_SOCKETFUNCTION, events_socket);
552   curl_multi_setopt(multi, CURLMOPT_SOCKETDATA, ev);
553 }
554 
555 
556 /* wait_or_timeout()
557  *
558  * waits for activity on any of the given sockets, or the timeout to trigger.
559  */
560 
wait_or_timeout(struct Curl_multi * multi,struct events * ev)561 static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
562 {
563   bool done = FALSE;
564   CURLMcode mcode;
565   CURLcode result = CURLE_OK;
566 
567   while(!done) {
568     CURLMsg *msg;
569     struct socketmonitor *m;
570     struct pollfd *f;
571     struct pollfd fds[4];
572     int numfds=0;
573     int pollrc;
574     int i;
575     struct timeval before;
576     struct timeval after;
577 
578     /* populate the fds[] array */
579     for(m = ev->list, f=&fds[0]; m; m = m->next) {
580       f->fd = m->socket.fd;
581       f->events = m->socket.events;
582       f->revents = 0;
583       /* fprintf(stderr, "poll() %d check socket %d\n", numfds, f->fd); */
584       f++;
585       numfds++;
586     }
587 
588     /* get the time stamp to use to figure out how long poll takes */
589     before = curlx_tvnow();
590 
591     /* wait for activity or timeout */
592     pollrc = Curl_poll(fds, numfds, (int)ev->ms);
593 
594     after = curlx_tvnow();
595 
596     ev->msbump = FALSE; /* reset here */
597 
598     if(0 == pollrc) {
599       /* timeout! */
600       ev->ms = 0;
601       /* fprintf(stderr, "call curl_multi_socket_action(TIMEOUT)\n"); */
602       mcode = curl_multi_socket_action(multi, CURL_SOCKET_TIMEOUT, 0,
603                                        &ev->running_handles);
604     }
605     else if(pollrc > 0) {
606       /* loop over the monitored sockets to see which ones had activity */
607       for(i = 0; i< numfds; i++) {
608         if(fds[i].revents) {
609           /* socket activity, tell libcurl */
610           int act = poll2cselect(fds[i].revents); /* convert */
611           infof(multi->easyp, "call curl_multi_socket_action(socket %d)\n",
612                 fds[i].fd);
613           mcode = curl_multi_socket_action(multi, fds[i].fd, act,
614                                            &ev->running_handles);
615         }
616       }
617 
618       if(!ev->msbump)
619         /* If nothing updated the timeout, we decrease it by the spent time.
620          * If it was updated, it has the new timeout time stored already.
621          */
622         ev->ms += curlx_tvdiff(after, before);
623 
624     }
625     else
626       return CURLE_RECV_ERROR;
627 
628     if(mcode)
629       return CURLE_URL_MALFORMAT; /* TODO: return a proper error! */
630 
631     /* we don't really care about the "msgs_in_queue" value returned in the
632        second argument */
633     msg = curl_multi_info_read(multi, &pollrc);
634     if(msg) {
635       result = msg->data.result;
636       done = TRUE;
637     }
638   }
639 
640   return result;
641 }
642 
643 
644 /* easy_events()
645  *
646  * Runs a transfer in a blocking manner using the events-based API
647  */
easy_events(struct Curl_multi * multi)648 static CURLcode easy_events(struct Curl_multi *multi)
649 {
650   struct events evs= {2, FALSE, 0, NULL, 0};
651 
652   /* if running event-based, do some further multi inits */
653   events_setup(multi, &evs);
654 
655   return wait_or_timeout(multi, &evs);
656 }
657 #else /* CURLDEBUG */
658 /* when not built with debug, this function doesn't exist */
659 #define easy_events(x) CURLE_NOT_BUILT_IN
660 #endif
661 
easy_transfer(struct Curl_multi * multi)662 static CURLcode easy_transfer(struct Curl_multi *multi)
663 {
664   bool done = FALSE;
665   CURLMcode mcode = CURLM_OK;
666   CURLcode result = CURLE_OK;
667   struct timeval before;
668   int without_fds = 0;  /* count number of consecutive returns from
669                            curl_multi_wait() without any filedescriptors */
670 
671   while(!done && !mcode) {
672     int still_running = 0;
673     int rc;
674 
675     before = curlx_tvnow();
676     mcode = curl_multi_wait(multi, NULL, 0, 1000, &rc);
677 
678     if(!mcode) {
679       if(!rc) {
680         struct timeval after = curlx_tvnow();
681 
682         /* If it returns without any filedescriptor instantly, we need to
683            avoid busy-looping during periods where it has nothing particular
684            to wait for */
685         if(curlx_tvdiff(after, before) <= 10) {
686           without_fds++;
687           if(without_fds > 2) {
688             int sleep_ms = without_fds < 10 ? (1 << (without_fds - 1)) : 1000;
689             Curl_wait_ms(sleep_ms);
690           }
691         }
692         else
693           /* it wasn't "instant", restart counter */
694           without_fds = 0;
695       }
696       else
697         /* got file descriptor, restart counter */
698         without_fds = 0;
699 
700       mcode = curl_multi_perform(multi, &still_running);
701     }
702 
703     /* only read 'still_running' if curl_multi_perform() return OK */
704     if(!mcode && !still_running) {
705       CURLMsg *msg = curl_multi_info_read(multi, &rc);
706       if(msg) {
707         result = msg->data.result;
708         done = TRUE;
709       }
710     }
711   }
712 
713   /* Make sure to return some kind of error if there was a multi problem */
714   if(mcode) {
715     result = (mcode == CURLM_OUT_OF_MEMORY) ? CURLE_OUT_OF_MEMORY :
716               /* The other multi errors should never happen, so return
717                  something suitably generic */
718               CURLE_BAD_FUNCTION_ARGUMENT;
719   }
720 
721   return result;
722 }
723 
724 
725 /*
726  * easy_perform() is the external interface that performs a blocking
727  * transfer as previously setup.
728  *
729  * CONCEPT: This function creates a multi handle, adds the easy handle to it,
730  * runs curl_multi_perform() until the transfer is done, then detaches the
731  * easy handle, destroys the multi handle and returns the easy handle's return
732  * code.
733  *
734  * REALITY: it can't just create and destroy the multi handle that easily. It
735  * needs to keep it around since if this easy handle is used again by this
736  * function, the same multi handle must be re-used so that the same pools and
737  * caches can be used.
738  *
739  * DEBUG: if 'events' is set TRUE, this function will use a replacement engine
740  * instead of curl_multi_perform() and use curl_multi_socket_action().
741  */
easy_perform(struct Curl_easy * data,bool events)742 static CURLcode easy_perform(struct Curl_easy *data, bool events)
743 {
744   struct Curl_multi *multi;
745   CURLMcode mcode;
746   CURLcode result = CURLE_OK;
747   SIGPIPE_VARIABLE(pipe_st);
748 
749   if(!data)
750     return CURLE_BAD_FUNCTION_ARGUMENT;
751 
752   if(data->multi) {
753     failf(data, "easy handle already used in multi handle");
754     return CURLE_FAILED_INIT;
755   }
756 
757   if(data->multi_easy)
758     multi = data->multi_easy;
759   else {
760     /* this multi handle will only ever have a single easy handled attached
761        to it, so make it use minimal hashes */
762     multi = Curl_multi_handle(1, 3);
763     if(!multi)
764       return CURLE_OUT_OF_MEMORY;
765     data->multi_easy = multi;
766   }
767 
768   /* Copy the MAXCONNECTS option to the multi handle */
769   curl_multi_setopt(multi, CURLMOPT_MAXCONNECTS, data->set.maxconnects);
770 
771   mcode = curl_multi_add_handle(multi, data);
772   if(mcode) {
773     curl_multi_cleanup(multi);
774     if(mcode == CURLM_OUT_OF_MEMORY)
775       return CURLE_OUT_OF_MEMORY;
776     else
777       return CURLE_FAILED_INIT;
778   }
779 
780   sigpipe_ignore(data, &pipe_st);
781 
782   /* assign this after curl_multi_add_handle() since that function checks for
783      it and rejects this handle otherwise */
784   data->multi = multi;
785 
786   /* run the transfer */
787   result = events ? easy_events(multi) : easy_transfer(multi);
788 
789   /* ignoring the return code isn't nice, but atm we can't really handle
790      a failure here, room for future improvement! */
791   (void)curl_multi_remove_handle(multi, data);
792 
793   sigpipe_restore(&pipe_st);
794 
795   /* The multi handle is kept alive, owned by the easy handle */
796   return result;
797 }
798 
799 
800 /*
801  * curl_easy_perform() is the external interface that performs a blocking
802  * transfer as previously setup.
803  */
curl_easy_perform(struct Curl_easy * data)804 CURLcode curl_easy_perform(struct Curl_easy *data)
805 {
806   return easy_perform(data, FALSE);
807 }
808 
809 #ifdef CURLDEBUG
810 /*
811  * curl_easy_perform_ev() is the external interface that performs a blocking
812  * transfer using the event-based API internally.
813  */
curl_easy_perform_ev(struct Curl_easy * data)814 CURLcode curl_easy_perform_ev(struct Curl_easy *data)
815 {
816   return easy_perform(data, TRUE);
817 }
818 
819 #endif
820 
821 /*
822  * curl_easy_cleanup() is the external interface to cleaning/freeing the given
823  * easy handle.
824  */
curl_easy_cleanup(struct Curl_easy * data)825 void curl_easy_cleanup(struct Curl_easy *data)
826 {
827   SIGPIPE_VARIABLE(pipe_st);
828 
829   if(!data)
830     return;
831 
832   sigpipe_ignore(data, &pipe_st);
833   Curl_close(data);
834   sigpipe_restore(&pipe_st);
835 }
836 
837 /*
838  * curl_easy_getinfo() is an external interface that allows an app to retrieve
839  * information from a performed transfer and similar.
840  */
841 #undef curl_easy_getinfo
curl_easy_getinfo(struct Curl_easy * data,CURLINFO info,...)842 CURLcode curl_easy_getinfo(struct Curl_easy *data, CURLINFO info, ...)
843 {
844   va_list arg;
845   void *paramp;
846   CURLcode result;
847 
848   va_start(arg, info);
849   paramp = va_arg(arg, void *);
850 
851   result = Curl_getinfo(data, info, paramp);
852 
853   va_end(arg);
854   return result;
855 }
856 
857 /*
858  * curl_easy_duphandle() is an external interface to allow duplication of a
859  * given input easy handle. The returned handle will be a new working handle
860  * with all options set exactly as the input source handle.
861  */
curl_easy_duphandle(struct Curl_easy * data)862 struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
863 {
864   struct Curl_easy *outcurl = calloc(1, sizeof(struct Curl_easy));
865   if(NULL == outcurl)
866     goto fail;
867 
868   /*
869    * We setup a few buffers we need. We should probably make them
870    * get setup on-demand in the code, as that would probably decrease
871    * the likeliness of us forgetting to init a buffer here in the future.
872    */
873   outcurl->state.headerbuff = malloc(HEADERSIZE);
874   if(!outcurl->state.headerbuff)
875     goto fail;
876   outcurl->state.headersize = HEADERSIZE;
877 
878   /* copy all userdefined values */
879   if(Curl_dupset(outcurl, data))
880     goto fail;
881 
882   /* the connection cache is setup on demand */
883   outcurl->state.conn_cache = NULL;
884 
885   outcurl->state.lastconnect = NULL;
886 
887   outcurl->progress.flags    = data->progress.flags;
888   outcurl->progress.callback = data->progress.callback;
889 
890   if(data->cookies) {
891     /* If cookies are enabled in the parent handle, we enable them
892        in the clone as well! */
893     outcurl->cookies = Curl_cookie_init(data,
894                                         data->cookies->filename,
895                                         outcurl->cookies,
896                                         data->set.cookiesession);
897     if(!outcurl->cookies)
898       goto fail;
899   }
900 
901   /* duplicate all values in 'change' */
902   if(data->change.cookielist) {
903     outcurl->change.cookielist =
904       Curl_slist_duplicate(data->change.cookielist);
905     if(!outcurl->change.cookielist)
906       goto fail;
907   }
908 
909   if(data->change.url) {
910     outcurl->change.url = strdup(data->change.url);
911     if(!outcurl->change.url)
912       goto fail;
913     outcurl->change.url_alloc = TRUE;
914   }
915 
916   if(data->change.referer) {
917     outcurl->change.referer = strdup(data->change.referer);
918     if(!outcurl->change.referer)
919       goto fail;
920     outcurl->change.referer_alloc = TRUE;
921   }
922 
923   /* Clone the resolver handle, if present, for the new handle */
924   if(Curl_resolver_duphandle(&outcurl->state.resolver,
925                              data->state.resolver))
926     goto fail;
927 
928   Curl_convert_setup(outcurl);
929 
930   Curl_initinfo(outcurl);
931 
932   outcurl->magic = CURLEASY_MAGIC_NUMBER;
933 
934   /* we reach this point and thus we are OK */
935 
936   return outcurl;
937 
938   fail:
939 
940   if(outcurl) {
941     curl_slist_free_all(outcurl->change.cookielist);
942     outcurl->change.cookielist = NULL;
943     Curl_safefree(outcurl->state.headerbuff);
944     Curl_safefree(outcurl->change.url);
945     Curl_safefree(outcurl->change.referer);
946     Curl_freeset(outcurl);
947     free(outcurl);
948   }
949 
950   return NULL;
951 }
952 
953 /*
954  * curl_easy_reset() is an external interface that allows an app to re-
955  * initialize a session handle to the default values.
956  */
curl_easy_reset(struct Curl_easy * data)957 void curl_easy_reset(struct Curl_easy *data)
958 {
959   Curl_safefree(data->state.pathbuffer);
960 
961   data->state.path = NULL;
962 
963   Curl_free_request_state(data);
964 
965   /* zero out UserDefined data: */
966   Curl_freeset(data);
967   memset(&data->set, 0, sizeof(struct UserDefined));
968   (void)Curl_init_userdefined(&data->set);
969 
970   /* zero out Progress data: */
971   memset(&data->progress, 0, sizeof(struct Progress));
972 
973   /* zero out PureInfo data: */
974   Curl_initinfo(data);
975 
976   data->progress.flags |= PGRS_HIDE;
977   data->state.current_speed = -1; /* init to negative == impossible */
978 }
979 
980 /*
981  * curl_easy_pause() allows an application to pause or unpause a specific
982  * transfer and direction. This function sets the full new state for the
983  * current connection this easy handle operates on.
984  *
985  * NOTE: if you have the receiving paused and you call this function to remove
986  * the pausing, you may get your write callback called at this point.
987  *
988  * Action is a bitmask consisting of CURLPAUSE_* bits in curl/curl.h
989  */
curl_easy_pause(struct Curl_easy * data,int action)990 CURLcode curl_easy_pause(struct Curl_easy *data, int action)
991 {
992   struct SingleRequest *k = &data->req;
993   CURLcode result = CURLE_OK;
994 
995   /* first switch off both pause bits */
996   int newstate = k->keepon &~ (KEEP_RECV_PAUSE| KEEP_SEND_PAUSE);
997 
998   /* set the new desired pause bits */
999   newstate |= ((action & CURLPAUSE_RECV)?KEEP_RECV_PAUSE:0) |
1000     ((action & CURLPAUSE_SEND)?KEEP_SEND_PAUSE:0);
1001 
1002   /* put it back in the keepon */
1003   k->keepon = newstate;
1004 
1005   if(!(newstate & KEEP_RECV_PAUSE) && data->state.tempwrite) {
1006     /* we have a buffer for sending that we now seem to be able to deliver
1007        since the receive pausing is lifted! */
1008 
1009     /* get the pointer in local copy since the function may return PAUSE
1010        again and then we'll get a new copy allocted and stored in
1011        the tempwrite variables */
1012     char *tempwrite = data->state.tempwrite;
1013 
1014     data->state.tempwrite = NULL;
1015     result = Curl_client_chop_write(data->easy_conn, data->state.tempwritetype,
1016                                     tempwrite, data->state.tempwritesize);
1017     free(tempwrite);
1018   }
1019 
1020   /* if there's no error and we're not pausing both directions, we want
1021      to have this handle checked soon */
1022   if(!result &&
1023      ((newstate&(KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) !=
1024       (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) )
1025     Curl_expire(data, 0); /* get this handle going again */
1026 
1027   return result;
1028 }
1029 
1030 
easy_connection(struct Curl_easy * data,curl_socket_t * sfd,struct connectdata ** connp)1031 static CURLcode easy_connection(struct Curl_easy *data,
1032                                 curl_socket_t *sfd,
1033                                 struct connectdata **connp)
1034 {
1035   if(data == NULL)
1036     return CURLE_BAD_FUNCTION_ARGUMENT;
1037 
1038   /* only allow these to be called on handles with CURLOPT_CONNECT_ONLY */
1039   if(!data->set.connect_only) {
1040     failf(data, "CONNECT_ONLY is required!");
1041     return CURLE_UNSUPPORTED_PROTOCOL;
1042   }
1043 
1044   *sfd = Curl_getconnectinfo(data, connp);
1045 
1046   if(*sfd == CURL_SOCKET_BAD) {
1047     failf(data, "Failed to get recent socket");
1048     return CURLE_UNSUPPORTED_PROTOCOL;
1049   }
1050 
1051   return CURLE_OK;
1052 }
1053 
1054 /*
1055  * Receives data from the connected socket. Use after successful
1056  * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
1057  * Returns CURLE_OK on success, error code on error.
1058  */
curl_easy_recv(struct Curl_easy * data,void * buffer,size_t buflen,size_t * n)1059 CURLcode curl_easy_recv(struct Curl_easy *data, void *buffer, size_t buflen,
1060                         size_t *n)
1061 {
1062   curl_socket_t sfd;
1063   CURLcode result;
1064   ssize_t n1;
1065   struct connectdata *c;
1066 
1067   result = easy_connection(data, &sfd, &c);
1068   if(result)
1069     return result;
1070 
1071   *n = 0;
1072   result = Curl_read(c, sfd, buffer, buflen, &n1);
1073 
1074   if(result)
1075     return result;
1076 
1077   *n = (size_t)n1;
1078 
1079   return CURLE_OK;
1080 }
1081 
1082 /*
1083  * Sends data over the connected socket. Use after successful
1084  * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
1085  */
curl_easy_send(struct Curl_easy * data,const void * buffer,size_t buflen,size_t * n)1086 CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer,
1087                         size_t buflen, size_t *n)
1088 {
1089   curl_socket_t sfd;
1090   CURLcode result;
1091   ssize_t n1;
1092   struct connectdata *c = NULL;
1093 
1094   result = easy_connection(data, &sfd, &c);
1095   if(result)
1096     return result;
1097 
1098   *n = 0;
1099   result = Curl_write(c, sfd, buffer, buflen, &n1);
1100 
1101   if(n1 == -1)
1102     return CURLE_SEND_ERROR;
1103 
1104   /* detect EAGAIN */
1105   if(!result && !n1)
1106     return CURLE_AGAIN;
1107 
1108   *n = (size_t)n1;
1109 
1110   return result;
1111 }
1112