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