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