diff options
Diffstat (limited to 'Utilities/cmcurl/lib/easy.c')
-rw-r--r-- | Utilities/cmcurl/lib/easy.c | 136 |
1 files changed, 114 insertions, 22 deletions
diff --git a/Utilities/cmcurl/lib/easy.c b/Utilities/cmcurl/lib/easy.c index bd9d695..b8ac1ef 100644 --- a/Utilities/cmcurl/lib/easy.c +++ b/Utilities/cmcurl/lib/easy.c @@ -18,6 +18,8 @@ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * + * SPDX-License-Identifier: curl + * ***************************************************************************/ #include "curl_setup.h" @@ -80,6 +82,8 @@ #include "altsvc.h" #include "hsts.h" +#include "easy_lock.h" + /* The last 3 #include files should be in this order */ #include "curl_printf.h" #include "curl_memory.h" @@ -89,6 +93,19 @@ static unsigned int initialized; static long init_flags; +#ifdef GLOBAL_INIT_IS_THREADSAFE + +static curl_simple_lock s_lock = CURL_SIMPLE_LOCK_INIT; +#define global_init_lock() curl_simple_lock_lock(&s_lock) +#define global_init_unlock() curl_simple_lock_unlock(&s_lock) + +#else + +#define global_init_lock() +#define global_init_unlock() + +#endif + /* * strdup (and other memory functions) is redefined in complicated * ways, but at this point it must be defined as the system-supplied strdup @@ -161,7 +178,7 @@ static CURLcode global_init(long flags, bool memoryfuncs) #endif #ifdef __AMIGA__ - if(!Curl_amiga_init()) { + if(Curl_amiga_init()) { DEBUGF(fprintf(stderr, "Error: Curl_amiga_init failed\n")); goto fail; } @@ -207,7 +224,14 @@ static CURLcode global_init(long flags, bool memoryfuncs) */ CURLcode curl_global_init(long flags) { - return global_init(flags, TRUE); + CURLcode result; + global_init_lock(); + + result = global_init(flags, TRUE); + + global_init_unlock(); + + return result; } /* @@ -218,15 +242,20 @@ CURLcode 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) { + CURLcode result; + /* Invalid input, return immediately */ if(!m || !f || !r || !s || !c) return CURLE_FAILED_INIT; + global_init_lock(); + if(initialized) { /* Already initialized, don't do it again, but bump the variable anyway to work like curl_global_init() and require the same amount of cleanup calls. */ initialized++; + global_init_unlock(); return CURLE_OK; } @@ -239,7 +268,11 @@ CURLcode curl_global_init_mem(long flags, curl_malloc_callback m, Curl_ccalloc = c; /* Call the actual init function, but without setting */ - return global_init(flags, FALSE); + result = global_init(flags, FALSE); + + global_init_unlock(); + + return result; } /** @@ -248,11 +281,17 @@ CURLcode curl_global_init_mem(long flags, curl_malloc_callback m, */ void curl_global_cleanup(void) { - if(!initialized) + global_init_lock(); + + if(!initialized) { + global_init_unlock(); return; + } - if(--initialized) + if(--initialized) { + global_init_unlock(); return; + } Curl_ssl_cleanup(); Curl_resolver_global_cleanup(); @@ -273,6 +312,25 @@ void curl_global_cleanup(void) #endif init_flags = 0; + + global_init_unlock(); +} + +/* + * curl_global_sslset() globally initializes the SSL backend to use. + */ +CURLsslset curl_global_sslset(curl_sslbackend id, const char *name, + const curl_ssl_backend ***avail) +{ + CURLsslset rc; + + global_init_lock(); + + rc = Curl_init_sslset_nolock(id, name, avail); + + global_init_unlock(); + + return rc; } /* @@ -285,14 +343,18 @@ struct Curl_easy *curl_easy_init(void) struct Curl_easy *data; /* Make sure we inited the global SSL stuff */ + global_init_lock(); + if(!initialized) { - result = curl_global_init(CURL_GLOBAL_DEFAULT); + result = global_init(CURL_GLOBAL_DEFAULT, TRUE); if(result) { /* something in the global init failed, return nothing */ DEBUGF(fprintf(stderr, "Error: curl_global_init failed\n")); + global_init_unlock(); return NULL; } } + global_init_unlock(); /* We use curl_open() with undefined URL so far */ result = Curl_open(&data); @@ -507,19 +569,23 @@ static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev) /* wait for activity or timeout */ pollrc = Curl_poll(fds, numfds, ev->ms); + if(pollrc < 0) + return CURLE_UNRECOVERABLE_POLL; after = Curl_now(); ev->msbump = FALSE; /* reset here */ - if(0 == pollrc) { + if(!pollrc) { /* timeout! */ ev->ms = 0; /* fprintf(stderr, "call curl_multi_socket_action(TIMEOUT)\n"); */ mcode = curl_multi_socket_action(multi, CURL_SOCKET_TIMEOUT, 0, &ev->running_handles); } - else if(pollrc > 0) { + else { + /* here pollrc is > 0 */ + /* loop over the monitored sockets to see which ones had activity */ for(i = 0; i< numfds; i++) { if(fds[i].revents) { @@ -545,8 +611,6 @@ static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev) } } } - else - return CURLE_RECV_ERROR; if(mcode) return CURLE_URL_MALFORMAT; @@ -662,7 +726,7 @@ static CURLcode easy_perform(struct Curl_easy *data, bool events) else { /* this multi handle will only ever have a single easy handled attached to it, so make it use minimal hashes */ - multi = Curl_multi_handle(1, 3); + multi = Curl_multi_handle(1, 3, 7); if(!multi) return CURLE_OUT_OF_MEMORY; data->multi_easy = multi; @@ -838,6 +902,7 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data) outcurl->progress.flags = data->progress.flags; outcurl->progress.callback = data->progress.callback; +#ifndef CURL_DISABLE_COOKIES if(data->cookies) { /* If cookies are enabled in the parent handle, we enable them in the clone as well! */ @@ -856,6 +921,7 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data) if(!outcurl->state.cookielist) goto fail; } +#endif if(data->state.url) { outcurl->state.url = strdup(data->state.url); @@ -878,7 +944,7 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data) goto fail; } -#ifdef USE_ALTSVC +#ifndef CURL_DISABLE_ALTSVC if(data->asi) { outcurl->asi = Curl_altsvc_init(); if(!outcurl->asi) @@ -937,8 +1003,10 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data) fail: if(outcurl) { +#ifndef CURL_DISABLE_COOKIES curl_slist_free_all(outcurl->state.cookielist); outcurl->state.cookielist = NULL; +#endif Curl_safefree(outcurl->state.buffer); Curl_dyn_free(&outcurl->state.headerb); Curl_safefree(outcurl->state.url); @@ -1065,6 +1133,16 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action) } } +#ifdef USE_HYPER + if(!(newstate & KEEP_SEND_PAUSE)) { + /* need to wake the send body waker */ + if(data->hyp.send_body_waker) { + hyper_waker_wake(data->hyp.send_body_waker); + data->hyp.send_body_waker = NULL; + } + } +#endif + /* if there's no error and we're not pausing both directions, we want to have this handle checked soon */ if((newstate & (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) != @@ -1093,8 +1171,7 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action) } -static CURLcode easy_connection(struct Curl_easy *data, - curl_socket_t *sfd, +static CURLcode easy_connection(struct Curl_easy *data, curl_socket_t *sfd, struct connectdata **connp) { if(!data) @@ -1153,11 +1230,12 @@ CURLcode curl_easy_recv(struct Curl_easy *data, void *buffer, size_t buflen, } /* - * Sends data over the connected socket. Use after successful - * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + * Sends data over the connected socket. + * + * This is the private internal version of curl_easy_send() */ -CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer, - size_t buflen, size_t *n) +CURLcode Curl_senddata(struct Curl_easy *data, const void *buffer, + size_t buflen, ssize_t *n) { curl_socket_t sfd; CURLcode result; @@ -1165,9 +1243,6 @@ CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer, struct connectdata *c = NULL; SIGPIPE_VARIABLE(pipe_st); - if(Curl_is_in_callback(data)) - return CURLE_RECURSIVE_API_CALL; - result = easy_connection(data, &sfd, &c); if(result) return result; @@ -1189,8 +1264,25 @@ CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer, if(!result && !n1) return CURLE_AGAIN; - *n = (size_t)n1; + *n = n1; + + return result; +} + +/* + * Sends data over the connected socket. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + */ +CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer, + size_t buflen, size_t *n) +{ + ssize_t written = 0; + CURLcode result; + if(Curl_is_in_callback(data)) + return CURLE_RECURSIVE_API_CALL; + result = Curl_senddata(data, buffer, buflen, &written); + *n = (size_t)written; return result; } |