• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2021, 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.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 "multiif.h"
65 #include "select.h"
66 #include "sendf.h" /* for failf function prototype */
67 #include "connect.h" /* for Curl_getconnectinfo */
68 #include "slist.h"
69 #include "mime.h"
70 #include "amigaos.h"
71 #include "non-ascii.h"
72 #include "warnless.h"
73 #include "multiif.h"
74 #include "sigpipe.h"
75 #include "vssh/ssh.h"
76 #include "setopt.h"
77 #include "http_digest.h"
78 #include "system_win32.h"
79 #include "http2.h"
80 #include "dynbuf.h"
81 #include "altsvc.h"
82 #include "hsts.h"
83 
84 /* The last 3 #include files should be in this order */
85 #include "curl_printf.h"
86 #include "curl_memory.h"
87 #include "memdebug.h"
88 #include "easy_lock.h"
89 
90 /* true globals -- for curl_global_init() and curl_global_cleanup() */
91 static unsigned int  initialized;
92 static long          init_flags;
93 
94 #ifdef GLOBAL_INIT_IS_THREADSAFE
95 
96 static curl_simple_lock s_lock = CURL_SIMPLE_LOCK_INIT;
97 #define global_init_lock() curl_simple_lock_lock(&s_lock)
98 #define global_init_unlock() curl_simple_lock_unlock(&s_lock)
99 
100 #else
101 
102 #define global_init_lock()
103 #define global_init_unlock()
104 
105 #endif
106 
107 /*
108  * strdup (and other memory functions) is redefined in complicated
109  * ways, but at this point it must be defined as the system-supplied strdup
110  * so the callback pointer is initialized correctly.
111  */
112 #if defined(_WIN32_WCE)
113 #define system_strdup _strdup
114 #elif !defined(HAVE_STRDUP)
115 #define system_strdup curlx_strdup
116 #else
117 #define system_strdup strdup
118 #endif
119 
120 #if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__)
121 #  pragma warning(disable:4232) /* MSVC extension, dllimport identity */
122 #endif
123 
124 /*
125  * If a memory-using function (like curl_getenv) is used before
126  * curl_global_init() is called, we need to have these pointers set already.
127  */
128 curl_malloc_callback Curl_cmalloc = (curl_malloc_callback)malloc;
129 curl_free_callback Curl_cfree = (curl_free_callback)free;
130 curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc;
131 curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)system_strdup;
132 curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc;
133 #if defined(WIN32) && defined(UNICODE)
134 curl_wcsdup_callback Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup;
135 #endif
136 
137 #if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__)
138 #  pragma warning(default:4232) /* MSVC extension, dllimport identity */
139 #endif
140 
141 #ifdef DEBUGBUILD
142 static char *leakpointer;
143 #endif
144 
145 /**
146  * curl_global_init() globally initializes curl given a bitwise set of the
147  * different features of what to initialize.
148  */
global_init(long flags,bool memoryfuncs)149 static CURLcode global_init(long flags, bool memoryfuncs)
150 {
151   if(initialized++)
152     return CURLE_OK;
153 
154   if(memoryfuncs) {
155     /* Setup the default memory functions here (again) */
156     Curl_cmalloc = (curl_malloc_callback)malloc;
157     Curl_cfree = (curl_free_callback)free;
158     Curl_crealloc = (curl_realloc_callback)realloc;
159     Curl_cstrdup = (curl_strdup_callback)system_strdup;
160     Curl_ccalloc = (curl_calloc_callback)calloc;
161 #if defined(WIN32) && defined(UNICODE)
162     Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup;
163 #endif
164   }
165 
166   if(!Curl_ssl_init()) {
167     DEBUGF(fprintf(stderr, "Error: Curl_ssl_init failed\n"));
168     goto fail;
169   }
170 
171 #ifdef WIN32
172   if(Curl_win32_init(flags)) {
173     DEBUGF(fprintf(stderr, "Error: win32_init failed\n"));
174     goto fail;
175   }
176 #endif
177 
178 #ifdef __AMIGA__
179   if(!Curl_amiga_init()) {
180     DEBUGF(fprintf(stderr, "Error: Curl_amiga_init failed\n"));
181     goto fail;
182   }
183 #endif
184 
185 #ifdef NETWARE
186   if(netware_init()) {
187     DEBUGF(fprintf(stderr, "Warning: LONG namespace not available\n"));
188   }
189 #endif
190 
191   if(Curl_resolver_global_init()) {
192     DEBUGF(fprintf(stderr, "Error: resolver_global_init failed\n"));
193     goto fail;
194   }
195 
196 #if defined(USE_SSH)
197   if(Curl_ssh_init()) {
198     goto fail;
199   }
200 #endif
201 
202 #ifdef USE_WOLFSSH
203   if(WS_SUCCESS != wolfSSH_Init()) {
204     DEBUGF(fprintf(stderr, "Error: wolfSSH_Init failed\n"));
205     return CURLE_FAILED_INIT;
206   }
207 #endif
208 
209   init_flags = flags;
210 
211 #ifdef DEBUGBUILD
212   if(getenv("CURL_GLOBAL_INIT"))
213     /* alloc data that will leak if *cleanup() is not called! */
214     leakpointer = malloc(1);
215 #endif
216 
217   return CURLE_OK;
218 
219   fail:
220   initialized--; /* undo the increase */
221   return CURLE_FAILED_INIT;
222 }
223 
224 
225 /**
226  * curl_global_init() globally initializes curl given a bitwise set of the
227  * different features of what to initialize.
228  */
curl_global_init(long flags)229 CURLcode curl_global_init(long flags)
230 {
231   CURLcode result;
232   global_init_lock();
233 
234   result = global_init(flags, TRUE);
235 
236   global_init_unlock();
237 
238   return result;
239 }
240 
241 /*
242  * curl_global_init_mem() globally initializes curl and also registers the
243  * user provided callback routines.
244  */
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)245 CURLcode curl_global_init_mem(long flags, curl_malloc_callback m,
246                               curl_free_callback f, curl_realloc_callback r,
247                               curl_strdup_callback s, curl_calloc_callback c)
248 {
249   CURLcode result;
250 
251   /* Invalid input, return immediately */
252   if(!m || !f || !r || !s || !c)
253     return CURLE_FAILED_INIT;
254 
255   global_init_lock();
256 
257   if(initialized) {
258     /* Already initialized, don't do it again, but bump the variable anyway to
259        work like curl_global_init() and require the same amount of cleanup
260        calls. */
261     initialized++;
262     global_init_unlock();
263     return CURLE_OK;
264   }
265 
266   /* set memory functions before global_init() in case it wants memory
267      functions */
268   Curl_cmalloc = m;
269   Curl_cfree = f;
270   Curl_cstrdup = s;
271   Curl_crealloc = r;
272   Curl_ccalloc = c;
273 
274   /* Call the actual init function, but without setting */
275   result = global_init(flags, FALSE);
276 
277   global_init_unlock();
278 
279   return result;
280 }
281 
282 /**
283  * curl_global_cleanup() globally cleanups curl, uses the value of
284  * "init_flags" to determine what needs to be cleaned up and what doesn't.
285  */
curl_global_cleanup(void)286 void curl_global_cleanup(void)
287 {
288   global_init_lock();
289 
290   if(!initialized) {
291     global_init_unlock();
292     return;
293   }
294 
295   if(--initialized) {
296     global_init_unlock();
297     return;
298   }
299 
300   Curl_ssl_cleanup();
301   Curl_resolver_global_cleanup();
302 
303 #ifdef WIN32
304   Curl_win32_cleanup(init_flags);
305 #endif
306 
307   Curl_amiga_cleanup();
308 
309   Curl_ssh_cleanup();
310 
311 #ifdef USE_WOLFSSH
312   (void)wolfSSH_Cleanup();
313 #endif
314 #ifdef DEBUGBUILD
315   free(leakpointer);
316 #endif
317 
318   init_flags  = 0;
319 
320   global_init_unlock();
321 }
322 
323 /*
324  * curl_easy_init() is the external interface to alloc, setup and init an
325  * easy handle that is returned. If anything goes wrong, NULL is returned.
326  */
curl_easy_init(void)327 struct Curl_easy *curl_easy_init(void)
328 {
329   CURLcode result;
330   struct Curl_easy *data;
331 
332   /* Make sure we inited the global SSL stuff */
333   global_init_lock();
334 
335   if(!initialized) {
336     result = global_init(CURL_GLOBAL_DEFAULT, TRUE);
337     if(result) {
338       /* something in the global init failed, return nothing */
339       DEBUGF(fprintf(stderr, "Error: curl_global_init failed\n"));
340       global_init_unlock();
341       return NULL;
342     }
343   }
344   global_init_unlock();
345 
346   /* We use curl_open() with undefined URL so far */
347   result = Curl_open(&data);
348   if(result) {
349     DEBUGF(fprintf(stderr, "Error: Curl_open failed\n"));
350     return NULL;
351   }
352 
353   return data;
354 }
355 
356 #ifdef CURLDEBUG
357 
358 struct socketmonitor {
359   struct socketmonitor *next; /* the next node in the list or NULL */
360   struct pollfd socket; /* socket info of what to monitor */
361 };
362 
363 struct events {
364   long ms;              /* timeout, run the timeout function when reached */
365   bool msbump;          /* set TRUE when timeout is set by callback */
366   int num_sockets;      /* number of nodes in the monitor list */
367   struct socketmonitor *list; /* list of sockets to monitor */
368   int running_handles;  /* store the returned number */
369 };
370 
371 /* events_timer
372  *
373  * Callback that gets called with a new value when the timeout should be
374  * updated.
375  */
376 
events_timer(struct Curl_multi * multi,long timeout_ms,void * userp)377 static int events_timer(struct Curl_multi *multi,    /* multi handle */
378                         long timeout_ms, /* see above */
379                         void *userp)    /* private callback pointer */
380 {
381   struct events *ev = userp;
382   (void)multi;
383   if(timeout_ms == -1)
384     /* timeout removed */
385     timeout_ms = 0;
386   else if(timeout_ms == 0)
387     /* timeout is already reached! */
388     timeout_ms = 1; /* trigger asap */
389 
390   ev->ms = timeout_ms;
391   ev->msbump = TRUE;
392   return 0;
393 }
394 
395 
396 /* poll2cselect
397  *
398  * convert from poll() bit definitions to libcurl's CURL_CSELECT_* ones
399  */
poll2cselect(int pollmask)400 static int poll2cselect(int pollmask)
401 {
402   int omask = 0;
403   if(pollmask & POLLIN)
404     omask |= CURL_CSELECT_IN;
405   if(pollmask & POLLOUT)
406     omask |= CURL_CSELECT_OUT;
407   if(pollmask & POLLERR)
408     omask |= CURL_CSELECT_ERR;
409   return omask;
410 }
411 
412 
413 /* socketcb2poll
414  *
415  * convert from libcurl' CURL_POLL_* bit definitions to poll()'s
416  */
socketcb2poll(int pollmask)417 static short socketcb2poll(int pollmask)
418 {
419   short omask = 0;
420   if(pollmask & CURL_POLL_IN)
421     omask |= POLLIN;
422   if(pollmask & CURL_POLL_OUT)
423     omask |= POLLOUT;
424   return omask;
425 }
426 
427 /* events_socket
428  *
429  * Callback that gets called with information about socket activity to
430  * monitor.
431  */
events_socket(struct Curl_easy * easy,curl_socket_t s,int what,void * userp,void * socketp)432 static int events_socket(struct Curl_easy *easy,      /* easy handle */
433                          curl_socket_t s, /* socket */
434                          int what,        /* see above */
435                          void *userp,     /* private callback
436                                              pointer */
437                          void *socketp)   /* private socket
438                                              pointer */
439 {
440   struct events *ev = userp;
441   struct socketmonitor *m;
442   struct socketmonitor *prev = NULL;
443 
444 #if defined(CURL_DISABLE_VERBOSE_STRINGS)
445   (void) easy;
446 #endif
447   (void)socketp;
448 
449   m = ev->list;
450   while(m) {
451     if(m->socket.fd == s) {
452 
453       if(what == CURL_POLL_REMOVE) {
454         struct socketmonitor *nxt = m->next;
455         /* remove this node from the list of monitored sockets */
456         if(prev)
457           prev->next = nxt;
458         else
459           ev->list = nxt;
460         free(m);
461         m = nxt;
462         infof(easy, "socket cb: socket %d REMOVED", s);
463       }
464       else {
465         /* The socket 's' is already being monitored, update the activity
466            mask. Convert from libcurl bitmask to the poll one. */
467         m->socket.events = socketcb2poll(what);
468         infof(easy, "socket cb: socket %d UPDATED as %s%s", s,
469               (what&CURL_POLL_IN)?"IN":"",
470               (what&CURL_POLL_OUT)?"OUT":"");
471       }
472       break;
473     }
474     prev = m;
475     m = m->next; /* move to next node */
476   }
477   if(!m) {
478     if(what == CURL_POLL_REMOVE) {
479       /* this happens a bit too often, libcurl fix perhaps? */
480       /* fprintf(stderr,
481          "%s: socket %d asked to be REMOVED but not present!\n",
482                  __func__, s); */
483     }
484     else {
485       m = malloc(sizeof(struct socketmonitor));
486       if(m) {
487         m->next = ev->list;
488         m->socket.fd = s;
489         m->socket.events = socketcb2poll(what);
490         m->socket.revents = 0;
491         ev->list = m;
492         infof(easy, "socket cb: socket %d ADDED as %s%s", s,
493               (what&CURL_POLL_IN)?"IN":"",
494               (what&CURL_POLL_OUT)?"OUT":"");
495       }
496       else
497         return CURLE_OUT_OF_MEMORY;
498     }
499   }
500 
501   return 0;
502 }
503 
504 
505 /*
506  * events_setup()
507  *
508  * Do the multi handle setups that only event-based transfers need.
509  */
events_setup(struct Curl_multi * multi,struct events * ev)510 static void events_setup(struct Curl_multi *multi, struct events *ev)
511 {
512   /* timer callback */
513   curl_multi_setopt(multi, CURLMOPT_TIMERFUNCTION, events_timer);
514   curl_multi_setopt(multi, CURLMOPT_TIMERDATA, ev);
515 
516   /* socket callback */
517   curl_multi_setopt(multi, CURLMOPT_SOCKETFUNCTION, events_socket);
518   curl_multi_setopt(multi, CURLMOPT_SOCKETDATA, ev);
519 }
520 
521 
522 /* wait_or_timeout()
523  *
524  * waits for activity on any of the given sockets, or the timeout to trigger.
525  */
526 
wait_or_timeout(struct Curl_multi * multi,struct events * ev)527 static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
528 {
529   bool done = FALSE;
530   CURLMcode mcode = CURLM_OK;
531   CURLcode result = CURLE_OK;
532 
533   while(!done) {
534     CURLMsg *msg;
535     struct socketmonitor *m;
536     struct pollfd *f;
537     struct pollfd fds[4];
538     int numfds = 0;
539     int pollrc;
540     int i;
541     struct curltime before;
542     struct curltime after;
543 
544     /* populate the fds[] array */
545     for(m = ev->list, f = &fds[0]; m; m = m->next) {
546       f->fd = m->socket.fd;
547       f->events = m->socket.events;
548       f->revents = 0;
549       /* fprintf(stderr, "poll() %d check socket %d\n", numfds, f->fd); */
550       f++;
551       numfds++;
552     }
553 
554     /* get the time stamp to use to figure out how long poll takes */
555     before = Curl_now();
556 
557     /* wait for activity or timeout */
558     pollrc = Curl_poll(fds, numfds, ev->ms);
559 
560     after = Curl_now();
561 
562     ev->msbump = FALSE; /* reset here */
563 
564     if(0 == pollrc) {
565       /* timeout! */
566       ev->ms = 0;
567       /* fprintf(stderr, "call curl_multi_socket_action(TIMEOUT)\n"); */
568       mcode = curl_multi_socket_action(multi, CURL_SOCKET_TIMEOUT, 0,
569                                        &ev->running_handles);
570     }
571     else if(pollrc > 0) {
572       /* loop over the monitored sockets to see which ones had activity */
573       for(i = 0; i< numfds; i++) {
574         if(fds[i].revents) {
575           /* socket activity, tell libcurl */
576           int act = poll2cselect(fds[i].revents); /* convert */
577           infof(multi->easyp, "call curl_multi_socket_action(socket %d)",
578                 fds[i].fd);
579           mcode = curl_multi_socket_action(multi, fds[i].fd, act,
580                                            &ev->running_handles);
581         }
582       }
583 
584       if(!ev->msbump) {
585         /* If nothing updated the timeout, we decrease it by the spent time.
586          * If it was updated, it has the new timeout time stored already.
587          */
588         timediff_t timediff = Curl_timediff(after, before);
589         if(timediff > 0) {
590           if(timediff > ev->ms)
591             ev->ms = 0;
592           else
593             ev->ms -= (long)timediff;
594         }
595       }
596     }
597     else
598       return CURLE_RECV_ERROR;
599 
600     if(mcode)
601       return CURLE_URL_MALFORMAT;
602 
603     /* we don't really care about the "msgs_in_queue" value returned in the
604        second argument */
605     msg = curl_multi_info_read(multi, &pollrc);
606     if(msg) {
607       result = msg->data.result;
608       done = TRUE;
609     }
610   }
611 
612   return result;
613 }
614 
615 
616 /* easy_events()
617  *
618  * Runs a transfer in a blocking manner using the events-based API
619  */
easy_events(struct Curl_multi * multi)620 static CURLcode easy_events(struct Curl_multi *multi)
621 {
622   /* this struct is made static to allow it to be used after this function
623      returns and curl_multi_remove_handle() is called */
624   static struct events evs = {2, FALSE, 0, NULL, 0};
625 
626   /* if running event-based, do some further multi inits */
627   events_setup(multi, &evs);
628 
629   return wait_or_timeout(multi, &evs);
630 }
631 #else /* CURLDEBUG */
632 /* when not built with debug, this function doesn't exist */
633 #define easy_events(x) CURLE_NOT_BUILT_IN
634 #endif
635 
easy_transfer(struct Curl_multi * multi)636 static CURLcode easy_transfer(struct Curl_multi *multi)
637 {
638   bool done = FALSE;
639   CURLMcode mcode = CURLM_OK;
640   CURLcode result = CURLE_OK;
641 
642   while(!done && !mcode) {
643     int still_running = 0;
644 
645     mcode = curl_multi_poll(multi, NULL, 0, 1000, NULL);
646 
647     if(!mcode)
648       mcode = curl_multi_perform(multi, &still_running);
649 
650     /* only read 'still_running' if curl_multi_perform() return OK */
651     if(!mcode && !still_running) {
652       int rc;
653       CURLMsg *msg = curl_multi_info_read(multi, &rc);
654       if(msg) {
655         result = msg->data.result;
656         done = TRUE;
657       }
658     }
659   }
660 
661   /* Make sure to return some kind of error if there was a multi problem */
662   if(mcode) {
663     result = (mcode == CURLM_OUT_OF_MEMORY) ? CURLE_OUT_OF_MEMORY :
664               /* The other multi errors should never happen, so return
665                  something suitably generic */
666               CURLE_BAD_FUNCTION_ARGUMENT;
667   }
668 
669   return result;
670 }
671 
672 
673 /*
674  * easy_perform() is the external interface that performs a blocking
675  * transfer as previously setup.
676  *
677  * CONCEPT: This function creates a multi handle, adds the easy handle to it,
678  * runs curl_multi_perform() until the transfer is done, then detaches the
679  * easy handle, destroys the multi handle and returns the easy handle's return
680  * code.
681  *
682  * REALITY: it can't just create and destroy the multi handle that easily. It
683  * needs to keep it around since if this easy handle is used again by this
684  * function, the same multi handle must be re-used so that the same pools and
685  * caches can be used.
686  *
687  * DEBUG: if 'events' is set TRUE, this function will use a replacement engine
688  * instead of curl_multi_perform() and use curl_multi_socket_action().
689  */
easy_perform(struct Curl_easy * data,bool events)690 static CURLcode easy_perform(struct Curl_easy *data, bool events)
691 {
692   struct Curl_multi *multi;
693   CURLMcode mcode;
694   CURLcode result = CURLE_OK;
695   SIGPIPE_VARIABLE(pipe_st);
696 
697   if(!data)
698     return CURLE_BAD_FUNCTION_ARGUMENT;
699 
700   if(data->set.errorbuffer)
701     /* clear this as early as possible */
702     data->set.errorbuffer[0] = 0;
703 
704   if(data->multi) {
705     failf(data, "easy handle already used in multi handle");
706     return CURLE_FAILED_INIT;
707   }
708 
709   if(data->multi_easy)
710     multi = data->multi_easy;
711   else {
712     /* this multi handle will only ever have a single easy handled attached
713        to it, so make it use minimal hashes */
714     multi = Curl_multi_handle(1, 3);
715     if(!multi)
716       return CURLE_OUT_OF_MEMORY;
717     data->multi_easy = multi;
718   }
719 
720   if(multi->in_callback)
721     return CURLE_RECURSIVE_API_CALL;
722 
723   /* Copy the MAXCONNECTS option to the multi handle */
724   curl_multi_setopt(multi, CURLMOPT_MAXCONNECTS, data->set.maxconnects);
725 
726   mcode = curl_multi_add_handle(multi, data);
727   if(mcode) {
728     curl_multi_cleanup(multi);
729     data->multi_easy = NULL;
730     if(mcode == CURLM_OUT_OF_MEMORY)
731       return CURLE_OUT_OF_MEMORY;
732     return CURLE_FAILED_INIT;
733   }
734 
735   sigpipe_ignore(data, &pipe_st);
736 
737   /* run the transfer */
738   result = events ? easy_events(multi) : easy_transfer(multi);
739 
740   /* ignoring the return code isn't nice, but atm we can't really handle
741      a failure here, room for future improvement! */
742   (void)curl_multi_remove_handle(multi, data);
743 
744   sigpipe_restore(&pipe_st);
745 
746   /* The multi handle is kept alive, owned by the easy handle */
747   return result;
748 }
749 
750 
751 /*
752  * curl_easy_perform() is the external interface that performs a blocking
753  * transfer as previously setup.
754  */
curl_easy_perform(struct Curl_easy * data)755 CURLcode curl_easy_perform(struct Curl_easy *data)
756 {
757   return easy_perform(data, FALSE);
758 }
759 
760 #ifdef CURLDEBUG
761 /*
762  * curl_easy_perform_ev() is the external interface that performs a blocking
763  * transfer using the event-based API internally.
764  */
curl_easy_perform_ev(struct Curl_easy * data)765 CURLcode curl_easy_perform_ev(struct Curl_easy *data)
766 {
767   return easy_perform(data, TRUE);
768 }
769 
770 #endif
771 
772 /*
773  * curl_easy_cleanup() is the external interface to cleaning/freeing the given
774  * easy handle.
775  */
curl_easy_cleanup(struct Curl_easy * data)776 void curl_easy_cleanup(struct Curl_easy *data)
777 {
778   SIGPIPE_VARIABLE(pipe_st);
779 
780   if(!data)
781     return;
782 
783   sigpipe_ignore(data, &pipe_st);
784   Curl_close(&data);
785   sigpipe_restore(&pipe_st);
786 }
787 
788 /*
789  * curl_easy_getinfo() is an external interface that allows an app to retrieve
790  * information from a performed transfer and similar.
791  */
792 #undef curl_easy_getinfo
curl_easy_getinfo(struct Curl_easy * data,CURLINFO info,...)793 CURLcode curl_easy_getinfo(struct Curl_easy *data, CURLINFO info, ...)
794 {
795   va_list arg;
796   void *paramp;
797   CURLcode result;
798 
799   va_start(arg, info);
800   paramp = va_arg(arg, void *);
801 
802   result = Curl_getinfo(data, info, paramp);
803 
804   va_end(arg);
805   return result;
806 }
807 
dupset(struct Curl_easy * dst,struct Curl_easy * src)808 static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src)
809 {
810   CURLcode result = CURLE_OK;
811   enum dupstring i;
812   enum dupblob j;
813 
814   /* Copy src->set into dst->set first, then deal with the strings
815      afterwards */
816   dst->set = src->set;
817   Curl_mime_initpart(&dst->set.mimepost, dst);
818 
819   /* clear all string pointers first */
820   memset(dst->set.str, 0, STRING_LAST * sizeof(char *));
821 
822   /* duplicate all strings */
823   for(i = (enum dupstring)0; i< STRING_LASTZEROTERMINATED; i++) {
824     result = Curl_setstropt(&dst->set.str[i], src->set.str[i]);
825     if(result)
826       return result;
827   }
828 
829   /* clear all blob pointers first */
830   memset(dst->set.blobs, 0, BLOB_LAST * sizeof(struct curl_blob *));
831   /* duplicate all blobs */
832   for(j = (enum dupblob)0; j < BLOB_LAST; j++) {
833     result = Curl_setblobopt(&dst->set.blobs[j], src->set.blobs[j]);
834     if(result)
835       return result;
836   }
837 
838   /* duplicate memory areas pointed to */
839   i = STRING_COPYPOSTFIELDS;
840   if(src->set.postfieldsize && src->set.str[i]) {
841     /* postfieldsize is curl_off_t, Curl_memdup() takes a size_t ... */
842     dst->set.str[i] = Curl_memdup(src->set.str[i],
843                                   curlx_sotouz(src->set.postfieldsize));
844     if(!dst->set.str[i])
845       return CURLE_OUT_OF_MEMORY;
846     /* point to the new copy */
847     dst->set.postfields = dst->set.str[i];
848   }
849 
850   /* Duplicate mime data. */
851   result = Curl_mime_duppart(&dst->set.mimepost, &src->set.mimepost);
852 
853   if(src->set.resolve)
854     dst->state.resolve = dst->set.resolve;
855 
856   return result;
857 }
858 
859 /*
860  * curl_easy_duphandle() is an external interface to allow duplication of a
861  * given input easy handle. The returned handle will be a new working handle
862  * with all options set exactly as the input source handle.
863  */
curl_easy_duphandle(struct Curl_easy * data)864 struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
865 {
866   struct Curl_easy *outcurl = calloc(1, sizeof(struct Curl_easy));
867   if(NULL == outcurl)
868     goto fail;
869 
870   /*
871    * We setup a few buffers we need. We should probably make them
872    * get setup on-demand in the code, as that would probably decrease
873    * the likeliness of us forgetting to init a buffer here in the future.
874    */
875   outcurl->set.buffer_size = data->set.buffer_size;
876 
877   /* copy all userdefined values */
878   if(dupset(outcurl, data))
879     goto fail;
880 
881   Curl_dyn_init(&outcurl->state.headerb, CURL_MAX_HTTP_HEADER);
882 
883   /* the connection cache is setup on demand */
884   outcurl->state.conn_cache = NULL;
885   outcurl->state.lastconnect_id = -1;
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->state.cookielist) {
903     outcurl->state.cookielist =
904       Curl_slist_duplicate(data->state.cookielist);
905     if(!outcurl->state.cookielist)
906       goto fail;
907   }
908 
909   if(data->state.url) {
910     outcurl->state.url = strdup(data->state.url);
911     if(!outcurl->state.url)
912       goto fail;
913     outcurl->state.url_alloc = TRUE;
914   }
915 
916   if(data->state.referer) {
917     outcurl->state.referer = strdup(data->state.referer);
918     if(!outcurl->state.referer)
919       goto fail;
920     outcurl->state.referer_alloc = TRUE;
921   }
922 
923   /* Reinitialize an SSL engine for the new handle
924    * note: the engine name has already been copied by dupset */
925   if(outcurl->set.str[STRING_SSL_ENGINE]) {
926     if(Curl_ssl_set_engine(outcurl, outcurl->set.str[STRING_SSL_ENGINE]))
927       goto fail;
928   }
929 
930 #ifdef USE_ALTSVC
931   if(data->asi) {
932     outcurl->asi = Curl_altsvc_init();
933     if(!outcurl->asi)
934       goto fail;
935     if(outcurl->set.str[STRING_ALTSVC])
936       (void)Curl_altsvc_load(outcurl->asi, outcurl->set.str[STRING_ALTSVC]);
937   }
938 #endif
939 #ifndef CURL_DISABLE_HSTS
940   if(data->hsts) {
941     outcurl->hsts = Curl_hsts_init();
942     if(!outcurl->hsts)
943       goto fail;
944     if(outcurl->set.str[STRING_HSTS])
945       (void)Curl_hsts_loadfile(outcurl,
946                                outcurl->hsts, outcurl->set.str[STRING_HSTS]);
947     (void)Curl_hsts_loadcb(outcurl, outcurl->hsts);
948   }
949 #endif
950   /* Clone the resolver handle, if present, for the new handle */
951   if(Curl_resolver_duphandle(outcurl,
952                              &outcurl->state.async.resolver,
953                              data->state.async.resolver))
954     goto fail;
955 
956 #ifdef USE_ARES
957   {
958     CURLcode rc;
959 
960     rc = Curl_set_dns_servers(outcurl, data->set.str[STRING_DNS_SERVERS]);
961     if(rc && rc != CURLE_NOT_BUILT_IN)
962       goto fail;
963 
964     rc = Curl_set_dns_interface(outcurl, data->set.str[STRING_DNS_INTERFACE]);
965     if(rc && rc != CURLE_NOT_BUILT_IN)
966       goto fail;
967 
968     rc = Curl_set_dns_local_ip4(outcurl, data->set.str[STRING_DNS_LOCAL_IP4]);
969     if(rc && rc != CURLE_NOT_BUILT_IN)
970       goto fail;
971 
972     rc = Curl_set_dns_local_ip6(outcurl, data->set.str[STRING_DNS_LOCAL_IP6]);
973     if(rc && rc != CURLE_NOT_BUILT_IN)
974       goto fail;
975   }
976 #endif /* USE_ARES */
977 
978   Curl_convert_setup(outcurl);
979 
980   Curl_initinfo(outcurl);
981 
982   outcurl->magic = CURLEASY_MAGIC_NUMBER;
983 
984   /* we reach this point and thus we are OK */
985 
986   return outcurl;
987 
988   fail:
989 
990   if(outcurl) {
991     curl_slist_free_all(outcurl->state.cookielist);
992     outcurl->state.cookielist = NULL;
993     Curl_safefree(outcurl->state.buffer);
994     Curl_dyn_free(&outcurl->state.headerb);
995     Curl_safefree(outcurl->state.url);
996     Curl_safefree(outcurl->state.referer);
997     Curl_altsvc_cleanup(&outcurl->asi);
998     Curl_hsts_cleanup(&outcurl->hsts);
999     Curl_freeset(outcurl);
1000     free(outcurl);
1001   }
1002 
1003   return NULL;
1004 }
1005 
1006 /*
1007  * curl_easy_reset() is an external interface that allows an app to re-
1008  * initialize a session handle to the default values.
1009  */
curl_easy_reset(struct Curl_easy * data)1010 void curl_easy_reset(struct Curl_easy *data)
1011 {
1012   Curl_free_request_state(data);
1013 
1014   /* zero out UserDefined data: */
1015   Curl_freeset(data);
1016   memset(&data->set, 0, sizeof(struct UserDefined));
1017   (void)Curl_init_userdefined(data);
1018 
1019   /* zero out Progress data: */
1020   memset(&data->progress, 0, sizeof(struct Progress));
1021 
1022   /* zero out PureInfo data: */
1023   Curl_initinfo(data);
1024 
1025   data->progress.flags |= PGRS_HIDE;
1026   data->state.current_speed = -1; /* init to negative == impossible */
1027   data->state.retrycount = 0;     /* reset the retry counter */
1028 
1029   /* zero out authentication data: */
1030   memset(&data->state.authhost, 0, sizeof(struct auth));
1031   memset(&data->state.authproxy, 0, sizeof(struct auth));
1032 
1033 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
1034   Curl_http_auth_cleanup_digest(data);
1035 #endif
1036 }
1037 
1038 /*
1039  * curl_easy_pause() allows an application to pause or unpause a specific
1040  * transfer and direction. This function sets the full new state for the
1041  * current connection this easy handle operates on.
1042  *
1043  * NOTE: if you have the receiving paused and you call this function to remove
1044  * the pausing, you may get your write callback called at this point.
1045  *
1046  * Action is a bitmask consisting of CURLPAUSE_* bits in curl/curl.h
1047  *
1048  * NOTE: This is one of few API functions that are allowed to be called from
1049  * within a callback.
1050  */
curl_easy_pause(struct Curl_easy * data,int action)1051 CURLcode curl_easy_pause(struct Curl_easy *data, int action)
1052 {
1053   struct SingleRequest *k;
1054   CURLcode result = CURLE_OK;
1055   int oldstate;
1056   int newstate;
1057 
1058   if(!GOOD_EASY_HANDLE(data) || !data->conn)
1059     /* crazy input, don't continue */
1060     return CURLE_BAD_FUNCTION_ARGUMENT;
1061 
1062   k = &data->req;
1063   oldstate = k->keepon & (KEEP_RECV_PAUSE| KEEP_SEND_PAUSE);
1064 
1065   /* first switch off both pause bits then set the new pause bits */
1066   newstate = (k->keepon &~ (KEEP_RECV_PAUSE| KEEP_SEND_PAUSE)) |
1067     ((action & CURLPAUSE_RECV)?KEEP_RECV_PAUSE:0) |
1068     ((action & CURLPAUSE_SEND)?KEEP_SEND_PAUSE:0);
1069 
1070   if((newstate & (KEEP_RECV_PAUSE| KEEP_SEND_PAUSE)) == oldstate) {
1071     /* Not changing any pause state, return */
1072     DEBUGF(infof(data, "pause: no change, early return"));
1073     return CURLE_OK;
1074   }
1075 
1076   /* Unpause parts in active mime tree. */
1077   if((k->keepon & ~newstate & KEEP_SEND_PAUSE) &&
1078      (data->mstate == MSTATE_PERFORMING ||
1079       data->mstate == MSTATE_RATELIMITING) &&
1080      data->state.fread_func == (curl_read_callback) Curl_mime_read) {
1081     Curl_mime_unpause(data->state.in);
1082   }
1083 
1084   /* put it back in the keepon */
1085   k->keepon = newstate;
1086 
1087   if(!(newstate & KEEP_RECV_PAUSE)) {
1088     Curl_http2_stream_pause(data, FALSE);
1089 
1090     if(data->state.tempcount) {
1091       /* there are buffers for sending that can be delivered as the receive
1092          pausing is lifted! */
1093       unsigned int i;
1094       unsigned int count = data->state.tempcount;
1095       struct tempbuf writebuf[3]; /* there can only be three */
1096 
1097       /* copy the structs to allow for immediate re-pausing */
1098       for(i = 0; i < data->state.tempcount; i++) {
1099         writebuf[i] = data->state.tempwrite[i];
1100         Curl_dyn_init(&data->state.tempwrite[i].b, DYN_PAUSE_BUFFER);
1101       }
1102       data->state.tempcount = 0;
1103 
1104       for(i = 0; i < count; i++) {
1105         /* even if one function returns error, this loops through and frees
1106            all buffers */
1107         if(!result)
1108           result = Curl_client_write(data, writebuf[i].type,
1109                                      Curl_dyn_ptr(&writebuf[i].b),
1110                                      Curl_dyn_len(&writebuf[i].b));
1111         Curl_dyn_free(&writebuf[i].b);
1112       }
1113 
1114       if(result)
1115         return result;
1116     }
1117   }
1118 
1119   /* if there's no error and we're not pausing both directions, we want
1120      to have this handle checked soon */
1121   if((newstate & (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) !=
1122      (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) {
1123     Curl_expire(data, 0, EXPIRE_RUN_NOW); /* get this handle going again */
1124 
1125     /* reset the too-slow time keeper */
1126     data->state.keeps_speed.tv_sec = 0;
1127 
1128     if(!data->state.tempcount)
1129       /* if not pausing again, force a recv/send check of this connection as
1130          the data might've been read off the socket already */
1131       data->conn->cselect_bits = CURL_CSELECT_IN | CURL_CSELECT_OUT;
1132     if(data->multi)
1133       Curl_update_timer(data->multi);
1134   }
1135 
1136   if(!data->state.done)
1137     /* This transfer may have been moved in or out of the bundle, update the
1138        corresponding socket callback, if used */
1139     Curl_updatesocket(data);
1140 
1141   return result;
1142 }
1143 
1144 
easy_connection(struct Curl_easy * data,curl_socket_t * sfd,struct connectdata ** connp)1145 static CURLcode easy_connection(struct Curl_easy *data,
1146                                 curl_socket_t *sfd,
1147                                 struct connectdata **connp)
1148 {
1149   if(!data)
1150     return CURLE_BAD_FUNCTION_ARGUMENT;
1151 
1152   /* only allow these to be called on handles with CURLOPT_CONNECT_ONLY */
1153   if(!data->set.connect_only) {
1154     failf(data, "CONNECT_ONLY is required!");
1155     return CURLE_UNSUPPORTED_PROTOCOL;
1156   }
1157 
1158   *sfd = Curl_getconnectinfo(data, connp);
1159 
1160   if(*sfd == CURL_SOCKET_BAD) {
1161     failf(data, "Failed to get recent socket");
1162     return CURLE_UNSUPPORTED_PROTOCOL;
1163   }
1164 
1165   return CURLE_OK;
1166 }
1167 
1168 /*
1169  * Receives data from the connected socket. Use after successful
1170  * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
1171  * Returns CURLE_OK on success, error code on error.
1172  */
curl_easy_recv(struct Curl_easy * data,void * buffer,size_t buflen,size_t * n)1173 CURLcode curl_easy_recv(struct Curl_easy *data, void *buffer, size_t buflen,
1174                         size_t *n)
1175 {
1176   curl_socket_t sfd;
1177   CURLcode result;
1178   ssize_t n1;
1179   struct connectdata *c;
1180 
1181   if(Curl_is_in_callback(data))
1182     return CURLE_RECURSIVE_API_CALL;
1183 
1184   result = easy_connection(data, &sfd, &c);
1185   if(result)
1186     return result;
1187 
1188   if(!data->conn)
1189     /* on first invoke, the transfer has been detached from the connection and
1190        needs to be reattached */
1191     Curl_attach_connnection(data, c);
1192 
1193   *n = 0;
1194   result = Curl_read(data, sfd, buffer, buflen, &n1);
1195 
1196   if(result)
1197     return result;
1198 
1199   *n = (size_t)n1;
1200 
1201   return CURLE_OK;
1202 }
1203 
1204 /*
1205  * Sends data over the connected socket. Use after successful
1206  * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
1207  */
curl_easy_send(struct Curl_easy * data,const void * buffer,size_t buflen,size_t * n)1208 CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer,
1209                         size_t buflen, size_t *n)
1210 {
1211   curl_socket_t sfd;
1212   CURLcode result;
1213   ssize_t n1;
1214   struct connectdata *c = NULL;
1215   SIGPIPE_VARIABLE(pipe_st);
1216 
1217   if(Curl_is_in_callback(data))
1218     return CURLE_RECURSIVE_API_CALL;
1219 
1220   result = easy_connection(data, &sfd, &c);
1221   if(result)
1222     return result;
1223 
1224   if(!data->conn)
1225     /* on first invoke, the transfer has been detached from the connection and
1226        needs to be reattached */
1227     Curl_attach_connnection(data, c);
1228 
1229   *n = 0;
1230   sigpipe_ignore(data, &pipe_st);
1231   result = Curl_write(data, sfd, buffer, buflen, &n1);
1232   sigpipe_restore(&pipe_st);
1233 
1234   if(n1 == -1)
1235     return CURLE_SEND_ERROR;
1236 
1237   /* detect EAGAIN */
1238   if(!result && !n1)
1239     return CURLE_AGAIN;
1240 
1241   *n = (size_t)n1;
1242 
1243   return result;
1244 }
1245 
1246 /*
1247  * Wrapper to call functions in Curl_conncache_foreach()
1248  *
1249  * Returns always 0.
1250  */
conn_upkeep(struct Curl_easy * data,struct connectdata * conn,void * param)1251 static int conn_upkeep(struct Curl_easy *data,
1252                        struct connectdata *conn,
1253                        void *param)
1254 {
1255   /* Param is unused. */
1256   (void)param;
1257 
1258   if(conn->handler->connection_check) {
1259     /* briefly attach the connection to this transfer for the purpose of
1260        checking it */
1261     Curl_attach_connnection(data, conn);
1262 
1263     /* Do a protocol-specific keepalive check on the connection. */
1264     conn->handler->connection_check(data, conn, CONNCHECK_KEEPALIVE);
1265     /* detach the connection again */
1266     Curl_detach_connnection(data);
1267   }
1268 
1269   return 0; /* continue iteration */
1270 }
1271 
upkeep(struct conncache * conn_cache,void * data)1272 static CURLcode upkeep(struct conncache *conn_cache, void *data)
1273 {
1274   /* Loop over every connection and make connection alive. */
1275   Curl_conncache_foreach(data,
1276                          conn_cache,
1277                          data,
1278                          conn_upkeep);
1279   return CURLE_OK;
1280 }
1281 
1282 /*
1283  * Performs connection upkeep for the given session handle.
1284  */
curl_easy_upkeep(struct Curl_easy * data)1285 CURLcode curl_easy_upkeep(struct Curl_easy *data)
1286 {
1287   /* Verify that we got an easy handle we can work with. */
1288   if(!GOOD_EASY_HANDLE(data))
1289     return CURLE_BAD_FUNCTION_ARGUMENT;
1290 
1291   if(data->multi_easy) {
1292     /* Use the common function to keep connections alive. */
1293     return upkeep(&data->multi_easy->conn_cache, data);
1294   }
1295   else {
1296     /* No connections, so just return success */
1297     return CURLE_OK;
1298   }
1299 }
1300