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