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