diff options
author | Nikita Slyusarev <nslus@yandex-team.com> | 2022-02-10 16:46:52 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:46:52 +0300 |
commit | cd77cecfc03a3eaf87816af28a33067c4f0cdb59 (patch) | |
tree | 1308e0bae862d52e0020d881fe758080437fe389 /contrib/libs/curl/lib/easy.c | |
parent | cdae02d225fb5b3afbb28990e79a7ac6c9125327 (diff) | |
download | ydb-cd77cecfc03a3eaf87816af28a33067c4f0cdb59.tar.gz |
Restoring authorship annotation for Nikita Slyusarev <nslus@yandex-team.com>. Commit 1 of 2.
Diffstat (limited to 'contrib/libs/curl/lib/easy.c')
-rw-r--r-- | contrib/libs/curl/lib/easy.c | 1502 |
1 files changed, 751 insertions, 751 deletions
diff --git a/contrib/libs/curl/lib/easy.c b/contrib/libs/curl/lib/easy.c index dc790b01df..4952cbfdbf 100644 --- a/contrib/libs/curl/lib/easy.c +++ b/contrib/libs/curl/lib/easy.c @@ -1,76 +1,76 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms * are also available at https://curl.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -#include "curl_setup.h" - -/* - * See comment in curl_memory.h for the explanation of this sanity check. - */ - -#ifdef CURLX_NO_MEMORY_CALLBACKS -#error "libcurl shall not ever be built with CURLX_NO_MEMORY_CALLBACKS defined" -#endif - -#ifdef HAVE_NETINET_IN_H -#include <netinet/in.h> -#endif -#ifdef HAVE_NETDB_H -#include <netdb.h> -#endif -#ifdef HAVE_ARPA_INET_H -#include <arpa/inet.h> -#endif -#ifdef HAVE_NET_IF_H -#include <net/if.h> -#endif -#ifdef HAVE_SYS_IOCTL_H -#include <sys/ioctl.h> -#endif - -#ifdef HAVE_SYS_PARAM_H -#include <sys/param.h> -#endif - -#include "urldata.h" -#include <curl/curl.h> -#include "transfer.h" + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +/* + * See comment in curl_memory.h for the explanation of this sanity check. + */ + +#ifdef CURLX_NO_MEMORY_CALLBACKS +#error "libcurl shall not ever be built with CURLX_NO_MEMORY_CALLBACKS defined" +#endif + +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif +#ifdef HAVE_NETDB_H +#include <netdb.h> +#endif +#ifdef HAVE_ARPA_INET_H +#include <arpa/inet.h> +#endif +#ifdef HAVE_NET_IF_H +#include <net/if.h> +#endif +#ifdef HAVE_SYS_IOCTL_H +#include <sys/ioctl.h> +#endif + +#ifdef HAVE_SYS_PARAM_H +#include <sys/param.h> +#endif + +#include "urldata.h" +#include <curl/curl.h> +#include "transfer.h" #include "vtls/vtls.h" -#include "url.h" -#include "getinfo.h" -#include "hostip.h" -#include "share.h" -#include "strdup.h" -#include "progress.h" -#include "easyif.h" +#include "url.h" +#include "getinfo.h" +#include "hostip.h" +#include "share.h" +#include "strdup.h" +#include "progress.h" +#include "easyif.h" #include "multiif.h" -#include "select.h" -#include "sendf.h" /* for failf function prototype */ -#include "connect.h" /* for Curl_getconnectinfo */ -#include "slist.h" +#include "select.h" +#include "sendf.h" /* for failf function prototype */ +#include "connect.h" /* for Curl_getconnectinfo */ +#include "slist.h" #include "mime.h" -#include "amigaos.h" -#include "non-ascii.h" -#include "warnless.h" -#include "multiif.h" +#include "amigaos.h" +#include "non-ascii.h" +#include "warnless.h" +#include "multiif.h" #include "sigpipe.h" #include "vssh/ssh.h" #include "setopt.h" @@ -80,59 +80,59 @@ #include "dynbuf.h" #include "altsvc.h" #include "hsts.h" - + /* The last 3 #include files should be in this order */ #include "curl_printf.h" #include "curl_memory.h" -#include "memdebug.h" - -/* true globals -- for curl_global_init() and curl_global_cleanup() */ -static unsigned int initialized; -static long init_flags; - -/* - * strdup (and other memory functions) is redefined in complicated - * ways, but at this point it must be defined as the system-supplied strdup - * so the callback pointer is initialized correctly. - */ -#if defined(_WIN32_WCE) -#define system_strdup _strdup -#elif !defined(HAVE_STRDUP) -#define system_strdup curlx_strdup -#else -#define system_strdup strdup -#endif - -#if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__) -# pragma warning(disable:4232) /* MSVC extension, dllimport identity */ -#endif - -/* - * If a memory-using function (like curl_getenv) is used before - * curl_global_init() is called, we need to have these pointers set already. - */ -curl_malloc_callback Curl_cmalloc = (curl_malloc_callback)malloc; -curl_free_callback Curl_cfree = (curl_free_callback)free; -curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc; -curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)system_strdup; -curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc; -#if defined(WIN32) && defined(UNICODE) -curl_wcsdup_callback Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup; -#endif - -#if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__) -# pragma warning(default:4232) /* MSVC extension, dllimport identity */ -#endif - -/** +#include "memdebug.h" + +/* true globals -- for curl_global_init() and curl_global_cleanup() */ +static unsigned int initialized; +static long init_flags; + +/* + * strdup (and other memory functions) is redefined in complicated + * ways, but at this point it must be defined as the system-supplied strdup + * so the callback pointer is initialized correctly. + */ +#if defined(_WIN32_WCE) +#define system_strdup _strdup +#elif !defined(HAVE_STRDUP) +#define system_strdup curlx_strdup +#else +#define system_strdup strdup +#endif + +#if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__) +# pragma warning(disable:4232) /* MSVC extension, dllimport identity */ +#endif + +/* + * If a memory-using function (like curl_getenv) is used before + * curl_global_init() is called, we need to have these pointers set already. + */ +curl_malloc_callback Curl_cmalloc = (curl_malloc_callback)malloc; +curl_free_callback Curl_cfree = (curl_free_callback)free; +curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc; +curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)system_strdup; +curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc; +#if defined(WIN32) && defined(UNICODE) +curl_wcsdup_callback Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup; +#endif + +#if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__) +# pragma warning(default:4232) /* MSVC extension, dllimport identity */ +#endif + +/** * curl_global_init() globally initializes curl given a bitwise set of the - * different features of what to initialize. - */ + * different features of what to initialize. + */ static CURLcode global_init(long flags, bool memoryfuncs) -{ - if(initialized++) - return CURLE_OK; - +{ + if(initialized++) + return CURLE_OK; + if(memoryfuncs) { /* Setup the default memory functions here (again) */ Curl_cmalloc = (curl_malloc_callback)malloc; @@ -140,41 +140,41 @@ static CURLcode global_init(long flags, bool memoryfuncs) Curl_crealloc = (curl_realloc_callback)realloc; Curl_cstrdup = (curl_strdup_callback)system_strdup; Curl_ccalloc = (curl_calloc_callback)calloc; -#if defined(WIN32) && defined(UNICODE) +#if defined(WIN32) && defined(UNICODE) Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup; -#endif +#endif } - + if(!Curl_ssl_init()) { DEBUGF(fprintf(stderr, "Error: Curl_ssl_init failed\n")); goto fail; } - + #ifdef WIN32 if(Curl_win32_init(flags)) { DEBUGF(fprintf(stderr, "Error: win32_init failed\n")); goto fail; } #endif - -#ifdef __AMIGA__ - if(!Curl_amiga_init()) { - DEBUGF(fprintf(stderr, "Error: Curl_amiga_init failed\n")); + +#ifdef __AMIGA__ + if(!Curl_amiga_init()) { + DEBUGF(fprintf(stderr, "Error: Curl_amiga_init failed\n")); goto fail; - } -#endif - -#ifdef NETWARE - if(netware_init()) { - DEBUGF(fprintf(stderr, "Warning: LONG namespace not available\n")); - } -#endif - + } +#endif + +#ifdef NETWARE + if(netware_init()) { + DEBUGF(fprintf(stderr, "Warning: LONG namespace not available\n")); + } +#endif + if(Curl_resolver_global_init()) { - DEBUGF(fprintf(stderr, "Error: resolver_global_init failed\n")); + DEBUGF(fprintf(stderr, "Error: resolver_global_init failed\n")); goto fail; - } - + } + #if defined(USE_SSH) if(Curl_ssh_init()) { goto fail; @@ -184,19 +184,19 @@ static CURLcode global_init(long flags, bool memoryfuncs) #ifdef USE_WOLFSSH if(WS_SUCCESS != wolfSSH_Init()) { DEBUGF(fprintf(stderr, "Error: wolfSSH_Init failed\n")); - return CURLE_FAILED_INIT; - } -#endif - + return CURLE_FAILED_INIT; + } +#endif + init_flags = flags; - + return CURLE_OK; fail: initialized--; /* undo the increase */ return CURLE_FAILED_INIT; -} - +} + /** * curl_global_init() globally initializes curl given a bitwise set of the @@ -207,26 +207,26 @@ CURLcode curl_global_init(long flags) return global_init(flags, TRUE); } -/* +/* * curl_global_init_mem() globally initializes curl and also registers the - * user provided callback routines. - */ -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) -{ - /* Invalid input, return immediately */ - if(!m || !f || !r || !s || !c) - return CURLE_FAILED_INIT; - + * user provided callback routines. + */ +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) +{ + /* Invalid input, return immediately */ + if(!m || !f || !r || !s || !c) + return CURLE_FAILED_INIT; + 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++; - return CURLE_OK; - } - + return CURLE_OK; + } + /* set memory functions before global_init() in case it wants memory functions */ Curl_cmalloc = m; @@ -237,197 +237,197 @@ CURLcode curl_global_init_mem(long flags, curl_malloc_callback m, /* Call the actual init function, but without setting */ return global_init(flags, FALSE); -} - -/** +} + +/** * curl_global_cleanup() globally cleanups curl, uses the value of - * "init_flags" to determine what needs to be cleaned up and what doesn't. - */ -void curl_global_cleanup(void) -{ - if(!initialized) - return; - - if(--initialized) - return; - + * "init_flags" to determine what needs to be cleaned up and what doesn't. + */ +void curl_global_cleanup(void) +{ + if(!initialized) + return; + + if(--initialized) + return; + Curl_ssl_cleanup(); - Curl_resolver_global_cleanup(); - + Curl_resolver_global_cleanup(); + #ifdef WIN32 Curl_win32_cleanup(init_flags); #endif - - Curl_amiga_cleanup(); - + + Curl_amiga_cleanup(); + Curl_ssh_cleanup(); - + #ifdef USE_WOLFSSH (void)wolfSSH_Cleanup(); #endif - init_flags = 0; -} - -/* - * curl_easy_init() is the external interface to alloc, setup and init an - * easy handle that is returned. If anything goes wrong, NULL is returned. - */ + init_flags = 0; +} + +/* + * curl_easy_init() is the external interface to alloc, setup and init an + * easy handle that is returned. If anything goes wrong, NULL is returned. + */ struct Curl_easy *curl_easy_init(void) -{ +{ CURLcode result; struct Curl_easy *data; - - /* Make sure we inited the global SSL stuff */ - if(!initialized) { + + /* Make sure we inited the global SSL stuff */ + if(!initialized) { result = curl_global_init(CURL_GLOBAL_DEFAULT); if(result) { - /* something in the global init failed, return nothing */ - DEBUGF(fprintf(stderr, "Error: curl_global_init failed\n")); - return NULL; - } - } - - /* We use curl_open() with undefined URL so far */ + /* something in the global init failed, return nothing */ + DEBUGF(fprintf(stderr, "Error: curl_global_init failed\n")); + return NULL; + } + } + + /* We use curl_open() with undefined URL so far */ result = Curl_open(&data); if(result) { - DEBUGF(fprintf(stderr, "Error: Curl_open failed\n")); - return NULL; - } - - return data; -} - -#ifdef CURLDEBUG - -struct socketmonitor { - struct socketmonitor *next; /* the next node in the list or NULL */ - struct pollfd socket; /* socket info of what to monitor */ -}; - -struct events { - long ms; /* timeout, run the timeout function when reached */ - bool msbump; /* set TRUE when timeout is set by callback */ - int num_sockets; /* number of nodes in the monitor list */ - struct socketmonitor *list; /* list of sockets to monitor */ - int running_handles; /* store the returned number */ -}; - -/* events_timer - * - * Callback that gets called with a new value when the timeout should be - * updated. - */ - + DEBUGF(fprintf(stderr, "Error: Curl_open failed\n")); + return NULL; + } + + return data; +} + +#ifdef CURLDEBUG + +struct socketmonitor { + struct socketmonitor *next; /* the next node in the list or NULL */ + struct pollfd socket; /* socket info of what to monitor */ +}; + +struct events { + long ms; /* timeout, run the timeout function when reached */ + bool msbump; /* set TRUE when timeout is set by callback */ + int num_sockets; /* number of nodes in the monitor list */ + struct socketmonitor *list; /* list of sockets to monitor */ + int running_handles; /* store the returned number */ +}; + +/* events_timer + * + * Callback that gets called with a new value when the timeout should be + * updated. + */ + static int events_timer(struct Curl_multi *multi, /* multi handle */ - long timeout_ms, /* see above */ - void *userp) /* private callback pointer */ -{ - struct events *ev = userp; - (void)multi; - if(timeout_ms == -1) - /* timeout removed */ - timeout_ms = 0; - else if(timeout_ms == 0) - /* timeout is already reached! */ - timeout_ms = 1; /* trigger asap */ - - ev->ms = timeout_ms; - ev->msbump = TRUE; - return 0; -} - - -/* poll2cselect - * - * convert from poll() bit definitions to libcurl's CURL_CSELECT_* ones - */ -static int poll2cselect(int pollmask) -{ + long timeout_ms, /* see above */ + void *userp) /* private callback pointer */ +{ + struct events *ev = userp; + (void)multi; + if(timeout_ms == -1) + /* timeout removed */ + timeout_ms = 0; + else if(timeout_ms == 0) + /* timeout is already reached! */ + timeout_ms = 1; /* trigger asap */ + + ev->ms = timeout_ms; + ev->msbump = TRUE; + return 0; +} + + +/* poll2cselect + * + * convert from poll() bit definitions to libcurl's CURL_CSELECT_* ones + */ +static int poll2cselect(int pollmask) +{ int omask = 0; - if(pollmask & POLLIN) - omask |= CURL_CSELECT_IN; - if(pollmask & POLLOUT) - omask |= CURL_CSELECT_OUT; - if(pollmask & POLLERR) - omask |= CURL_CSELECT_ERR; - return omask; -} - - -/* socketcb2poll - * - * convert from libcurl' CURL_POLL_* bit definitions to poll()'s - */ -static short socketcb2poll(int pollmask) -{ + if(pollmask & POLLIN) + omask |= CURL_CSELECT_IN; + if(pollmask & POLLOUT) + omask |= CURL_CSELECT_OUT; + if(pollmask & POLLERR) + omask |= CURL_CSELECT_ERR; + return omask; +} + + +/* socketcb2poll + * + * convert from libcurl' CURL_POLL_* bit definitions to poll()'s + */ +static short socketcb2poll(int pollmask) +{ short omask = 0; - if(pollmask & CURL_POLL_IN) - omask |= POLLIN; - if(pollmask & CURL_POLL_OUT) - omask |= POLLOUT; - return omask; -} - -/* events_socket - * - * Callback that gets called with information about socket activity to - * monitor. - */ + if(pollmask & CURL_POLL_IN) + omask |= POLLIN; + if(pollmask & CURL_POLL_OUT) + omask |= POLLOUT; + return omask; +} + +/* events_socket + * + * Callback that gets called with information about socket activity to + * monitor. + */ static int events_socket(struct Curl_easy *easy, /* easy handle */ - curl_socket_t s, /* socket */ - int what, /* see above */ - void *userp, /* private callback - pointer */ - void *socketp) /* private socket - pointer */ -{ - struct events *ev = userp; - struct socketmonitor *m; + curl_socket_t s, /* socket */ + int what, /* see above */ + void *userp, /* private callback + pointer */ + void *socketp) /* private socket + pointer */ +{ + struct events *ev = userp; + struct socketmonitor *m; struct socketmonitor *prev = NULL; #if defined(CURL_DISABLE_VERBOSE_STRINGS) (void) easy; #endif - (void)socketp; - - m = ev->list; - while(m) { - if(m->socket.fd == s) { - - if(what == CURL_POLL_REMOVE) { - struct socketmonitor *nxt = m->next; - /* remove this node from the list of monitored sockets */ - if(prev) - prev->next = nxt; - else - ev->list = nxt; - free(m); - m = nxt; - infof(easy, "socket cb: socket %d REMOVED\n", s); - } - else { - /* The socket 's' is already being monitored, update the activity - mask. Convert from libcurl bitmask to the poll one. */ - m->socket.events = socketcb2poll(what); - infof(easy, "socket cb: socket %d UPDATED as %s%s\n", s, + (void)socketp; + + m = ev->list; + while(m) { + if(m->socket.fd == s) { + + if(what == CURL_POLL_REMOVE) { + struct socketmonitor *nxt = m->next; + /* remove this node from the list of monitored sockets */ + if(prev) + prev->next = nxt; + else + ev->list = nxt; + free(m); + m = nxt; + infof(easy, "socket cb: socket %d REMOVED\n", s); + } + else { + /* The socket 's' is already being monitored, update the activity + mask. Convert from libcurl bitmask to the poll one. */ + m->socket.events = socketcb2poll(what); + infof(easy, "socket cb: socket %d UPDATED as %s%s\n", s, (what&CURL_POLL_IN)?"IN":"", (what&CURL_POLL_OUT)?"OUT":""); - } - break; - } - prev = m; - m = m->next; /* move to next node */ - } - if(!m) { - if(what == CURL_POLL_REMOVE) { - /* this happens a bit too often, libcurl fix perhaps? */ - /* fprintf(stderr, - "%s: socket %d asked to be REMOVED but not present!\n", - __func__, s); */ - } - else { - m = malloc(sizeof(struct socketmonitor)); + } + break; + } + prev = m; + m = m->next; /* move to next node */ + } + if(!m) { + if(what == CURL_POLL_REMOVE) { + /* this happens a bit too often, libcurl fix perhaps? */ + /* fprintf(stderr, + "%s: socket %d asked to be REMOVED but not present!\n", + __func__, s); */ + } + else { + m = malloc(sizeof(struct socketmonitor)); if(m) { m->next = ev->list; m->socket.fd = s; @@ -440,96 +440,96 @@ static int events_socket(struct Curl_easy *easy, /* easy handle */ } else return CURLE_OUT_OF_MEMORY; - } - } - - return 0; -} - - -/* - * events_setup() - * - * Do the multi handle setups that only event-based transfers need. - */ + } + } + + return 0; +} + + +/* + * events_setup() + * + * Do the multi handle setups that only event-based transfers need. + */ static void events_setup(struct Curl_multi *multi, struct events *ev) -{ - /* timer callback */ - curl_multi_setopt(multi, CURLMOPT_TIMERFUNCTION, events_timer); - curl_multi_setopt(multi, CURLMOPT_TIMERDATA, ev); - - /* socket callback */ - curl_multi_setopt(multi, CURLMOPT_SOCKETFUNCTION, events_socket); - curl_multi_setopt(multi, CURLMOPT_SOCKETDATA, ev); -} - - -/* wait_or_timeout() - * - * waits for activity on any of the given sockets, or the timeout to trigger. - */ - -static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev) -{ - bool done = FALSE; +{ + /* timer callback */ + curl_multi_setopt(multi, CURLMOPT_TIMERFUNCTION, events_timer); + curl_multi_setopt(multi, CURLMOPT_TIMERDATA, ev); + + /* socket callback */ + curl_multi_setopt(multi, CURLMOPT_SOCKETFUNCTION, events_socket); + curl_multi_setopt(multi, CURLMOPT_SOCKETDATA, ev); +} + + +/* wait_or_timeout() + * + * waits for activity on any of the given sockets, or the timeout to trigger. + */ + +static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev) +{ + bool done = FALSE; CURLMcode mcode = CURLM_OK; CURLcode result = CURLE_OK; - - while(!done) { - CURLMsg *msg; - struct socketmonitor *m; - struct pollfd *f; - struct pollfd fds[4]; + + while(!done) { + CURLMsg *msg; + struct socketmonitor *m; + struct pollfd *f; + struct pollfd fds[4]; int numfds = 0; - int pollrc; - int i; + int pollrc; + int i; struct curltime before; struct curltime after; - - /* populate the fds[] array */ + + /* populate the fds[] array */ for(m = ev->list, f = &fds[0]; m; m = m->next) { - f->fd = m->socket.fd; - f->events = m->socket.events; - f->revents = 0; - /* fprintf(stderr, "poll() %d check socket %d\n", numfds, f->fd); */ - f++; - numfds++; - } - - /* get the time stamp to use to figure out how long poll takes */ + f->fd = m->socket.fd; + f->events = m->socket.events; + f->revents = 0; + /* fprintf(stderr, "poll() %d check socket %d\n", numfds, f->fd); */ + f++; + numfds++; + } + + /* get the time stamp to use to figure out how long poll takes */ before = Curl_now(); - - /* wait for activity or timeout */ + + /* wait for activity or timeout */ pollrc = Curl_poll(fds, numfds, ev->ms); - + after = Curl_now(); - - ev->msbump = FALSE; /* reset here */ - - if(0 == pollrc) { - /* timeout! */ - ev->ms = 0; + + ev->msbump = FALSE; /* reset here */ + + if(0 == 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) { - /* loop over the monitored sockets to see which ones had activity */ - for(i = 0; i< numfds; i++) { - if(fds[i].revents) { - /* socket activity, tell libcurl */ - int act = poll2cselect(fds[i].revents); /* convert */ + mcode = curl_multi_socket_action(multi, CURL_SOCKET_TIMEOUT, 0, + &ev->running_handles); + } + else if(pollrc > 0) { + /* loop over the monitored sockets to see which ones had activity */ + for(i = 0; i< numfds; i++) { + if(fds[i].revents) { + /* socket activity, tell libcurl */ + int act = poll2cselect(fds[i].revents); /* convert */ infof(multi->easyp, "call curl_multi_socket_action(socket %d)\n", - fds[i].fd); - mcode = curl_multi_socket_action(multi, fds[i].fd, act, - &ev->running_handles); - } - } - + fds[i].fd); + mcode = curl_multi_socket_action(multi, fds[i].fd, act, + &ev->running_handles); + } + } + if(!ev->msbump) { - /* If nothing updated the timeout, we decrease it by the spent time. - * If it was updated, it has the new timeout time stored already. - */ + /* If nothing updated the timeout, we decrease it by the spent time. + * If it was updated, it has the new timeout time stored already. + */ timediff_t timediff = Curl_timediff(after, before); if(timediff > 0) { if(timediff > ev->ms) @@ -541,67 +541,67 @@ static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev) } else return CURLE_RECV_ERROR; - - if(mcode) + + if(mcode) return CURLE_URL_MALFORMAT; - - /* we don't really care about the "msgs_in_queue" value returned in the - second argument */ - msg = curl_multi_info_read(multi, &pollrc); - if(msg) { + + /* we don't really care about the "msgs_in_queue" value returned in the + second argument */ + msg = curl_multi_info_read(multi, &pollrc); + if(msg) { result = msg->data.result; - done = TRUE; - } - } - + done = TRUE; + } + } + return result; -} - - -/* easy_events() - * - * Runs a transfer in a blocking manner using the events-based API - */ +} + + +/* easy_events() + * + * Runs a transfer in a blocking manner using the events-based API + */ static CURLcode easy_events(struct Curl_multi *multi) -{ +{ /* this struct is made static to allow it to be used after this function returns and curl_multi_remove_handle() is called */ static struct events evs = {2, FALSE, 0, NULL, 0}; - - /* if running event-based, do some further multi inits */ - events_setup(multi, &evs); - - return wait_or_timeout(multi, &evs); -} -#else /* CURLDEBUG */ -/* when not built with debug, this function doesn't exist */ -#define easy_events(x) CURLE_NOT_BUILT_IN -#endif - + + /* if running event-based, do some further multi inits */ + events_setup(multi, &evs); + + return wait_or_timeout(multi, &evs); +} +#else /* CURLDEBUG */ +/* when not built with debug, this function doesn't exist */ +#define easy_events(x) CURLE_NOT_BUILT_IN +#endif + static CURLcode easy_transfer(struct Curl_multi *multi) -{ - bool done = FALSE; - CURLMcode mcode = CURLM_OK; +{ + bool done = FALSE; + CURLMcode mcode = CURLM_OK; CURLcode result = CURLE_OK; - - while(!done && !mcode) { + + while(!done && !mcode) { int still_running = 0; - + mcode = curl_multi_poll(multi, NULL, 0, 1000, NULL); - + if(!mcode) - mcode = curl_multi_perform(multi, &still_running); - - /* only read 'still_running' if curl_multi_perform() return OK */ + mcode = curl_multi_perform(multi, &still_running); + + /* only read 'still_running' if curl_multi_perform() return OK */ if(!mcode && !still_running) { - int rc; - CURLMsg *msg = curl_multi_info_read(multi, &rc); - if(msg) { + int rc; + CURLMsg *msg = curl_multi_info_read(multi, &rc); + if(msg) { result = msg->data.result; - done = TRUE; - } - } - } + done = TRUE; + } + } + } /* Make sure to return some kind of error if there was a multi problem */ if(mcode) { @@ -612,144 +612,144 @@ static CURLcode easy_transfer(struct Curl_multi *multi) } return result; -} - - -/* - * easy_perform() is the external interface that performs a blocking - * transfer as previously setup. - * - * CONCEPT: This function creates a multi handle, adds the easy handle to it, - * runs curl_multi_perform() until the transfer is done, then detaches the - * easy handle, destroys the multi handle and returns the easy handle's return - * code. - * - * REALITY: it can't just create and destroy the multi handle that easily. It - * needs to keep it around since if this easy handle is used again by this - * function, the same multi handle must be re-used so that the same pools and - * caches can be used. - * - * DEBUG: if 'events' is set TRUE, this function will use a replacement engine - * instead of curl_multi_perform() and use curl_multi_socket_action(). - */ +} + + +/* + * easy_perform() is the external interface that performs a blocking + * transfer as previously setup. + * + * CONCEPT: This function creates a multi handle, adds the easy handle to it, + * runs curl_multi_perform() until the transfer is done, then detaches the + * easy handle, destroys the multi handle and returns the easy handle's return + * code. + * + * REALITY: it can't just create and destroy the multi handle that easily. It + * needs to keep it around since if this easy handle is used again by this + * function, the same multi handle must be re-used so that the same pools and + * caches can be used. + * + * DEBUG: if 'events' is set TRUE, this function will use a replacement engine + * instead of curl_multi_perform() and use curl_multi_socket_action(). + */ static CURLcode easy_perform(struct Curl_easy *data, bool events) -{ +{ struct Curl_multi *multi; - CURLMcode mcode; + CURLMcode mcode; CURLcode result = CURLE_OK; - SIGPIPE_VARIABLE(pipe_st); - - if(!data) - return CURLE_BAD_FUNCTION_ARGUMENT; - + SIGPIPE_VARIABLE(pipe_st); + + if(!data) + return CURLE_BAD_FUNCTION_ARGUMENT; + if(data->set.errorbuffer) /* clear this as early as possible */ data->set.errorbuffer[0] = 0; - if(data->multi) { + if(data->multi) { failf(data, "easy handle already used in multi handle"); - return CURLE_FAILED_INIT; - } - - if(data->multi_easy) - multi = data->multi_easy; - 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); - if(!multi) - return CURLE_OUT_OF_MEMORY; - data->multi_easy = multi; - } - + return CURLE_FAILED_INIT; + } + + if(data->multi_easy) + multi = data->multi_easy; + 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); + if(!multi) + return CURLE_OUT_OF_MEMORY; + data->multi_easy = multi; + } + if(multi->in_callback) return CURLE_RECURSIVE_API_CALL; - /* Copy the MAXCONNECTS option to the multi handle */ - curl_multi_setopt(multi, CURLMOPT_MAXCONNECTS, data->set.maxconnects); - - mcode = curl_multi_add_handle(multi, data); - if(mcode) { - curl_multi_cleanup(multi); + /* Copy the MAXCONNECTS option to the multi handle */ + curl_multi_setopt(multi, CURLMOPT_MAXCONNECTS, data->set.maxconnects); + + mcode = curl_multi_add_handle(multi, data); + if(mcode) { + curl_multi_cleanup(multi); data->multi_easy = NULL; - if(mcode == CURLM_OUT_OF_MEMORY) - return CURLE_OUT_OF_MEMORY; + if(mcode == CURLM_OUT_OF_MEMORY) + return CURLE_OUT_OF_MEMORY; return CURLE_FAILED_INIT; - } - - sigpipe_ignore(data, &pipe_st); - - /* run the transfer */ + } + + sigpipe_ignore(data, &pipe_st); + + /* run the transfer */ result = events ? easy_events(multi) : easy_transfer(multi); - - /* ignoring the return code isn't nice, but atm we can't really handle - a failure here, room for future improvement! */ - (void)curl_multi_remove_handle(multi, data); - - sigpipe_restore(&pipe_st); - - /* The multi handle is kept alive, owned by the easy handle */ + + /* ignoring the return code isn't nice, but atm we can't really handle + a failure here, room for future improvement! */ + (void)curl_multi_remove_handle(multi, data); + + sigpipe_restore(&pipe_st); + + /* The multi handle is kept alive, owned by the easy handle */ return result; -} - - -/* - * curl_easy_perform() is the external interface that performs a blocking - * transfer as previously setup. - */ +} + + +/* + * curl_easy_perform() is the external interface that performs a blocking + * transfer as previously setup. + */ CURLcode curl_easy_perform(struct Curl_easy *data) -{ +{ return easy_perform(data, FALSE); -} - -#ifdef CURLDEBUG -/* - * curl_easy_perform_ev() is the external interface that performs a blocking - * transfer using the event-based API internally. - */ +} + +#ifdef CURLDEBUG +/* + * curl_easy_perform_ev() is the external interface that performs a blocking + * transfer using the event-based API internally. + */ CURLcode curl_easy_perform_ev(struct Curl_easy *data) -{ +{ return easy_perform(data, TRUE); -} - -#endif - -/* - * curl_easy_cleanup() is the external interface to cleaning/freeing the given - * easy handle. - */ +} + +#endif + +/* + * curl_easy_cleanup() is the external interface to cleaning/freeing the given + * easy handle. + */ void curl_easy_cleanup(struct Curl_easy *data) -{ - SIGPIPE_VARIABLE(pipe_st); - - if(!data) - return; - - sigpipe_ignore(data, &pipe_st); +{ + SIGPIPE_VARIABLE(pipe_st); + + if(!data) + return; + + sigpipe_ignore(data, &pipe_st); Curl_close(&data); - sigpipe_restore(&pipe_st); -} - -/* - * curl_easy_getinfo() is an external interface that allows an app to retrieve - * information from a performed transfer and similar. - */ -#undef curl_easy_getinfo + sigpipe_restore(&pipe_st); +} + +/* + * curl_easy_getinfo() is an external interface that allows an app to retrieve + * information from a performed transfer and similar. + */ +#undef curl_easy_getinfo CURLcode curl_easy_getinfo(struct Curl_easy *data, CURLINFO info, ...) -{ - va_list arg; - void *paramp; +{ + va_list arg; + void *paramp; CURLcode result; - - va_start(arg, info); - paramp = va_arg(arg, void *); - + + va_start(arg, info); + paramp = va_arg(arg, void *); + result = Curl_getinfo(data, info, paramp); - - va_end(arg); + + va_end(arg); return result; -} - +} + static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src) { CURLcode result = CURLE_OK; @@ -802,70 +802,70 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src) return result; } -/* - * curl_easy_duphandle() is an external interface to allow duplication of a - * given input easy handle. The returned handle will be a new working handle - * with all options set exactly as the input source handle. - */ +/* + * curl_easy_duphandle() is an external interface to allow duplication of a + * given input easy handle. The returned handle will be a new working handle + * with all options set exactly as the input source handle. + */ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data) -{ +{ struct Curl_easy *outcurl = calloc(1, sizeof(struct Curl_easy)); - if(NULL == outcurl) - goto fail; - - /* - * We setup a few buffers we need. We should probably make them - * get setup on-demand in the code, as that would probably decrease - * the likeliness of us forgetting to init a buffer here in the future. - */ + if(NULL == outcurl) + goto fail; + + /* + * We setup a few buffers we need. We should probably make them + * get setup on-demand in the code, as that would probably decrease + * the likeliness of us forgetting to init a buffer here in the future. + */ outcurl->set.buffer_size = data->set.buffer_size; - /* copy all userdefined values */ + /* copy all userdefined values */ if(dupset(outcurl, data)) - goto fail; - + goto fail; + Curl_dyn_init(&outcurl->state.headerb, CURL_MAX_HTTP_HEADER); - /* the connection cache is setup on demand */ - outcurl->state.conn_cache = NULL; + /* the connection cache is setup on demand */ + outcurl->state.conn_cache = NULL; outcurl->state.lastconnect_id = -1; - - outcurl->progress.flags = data->progress.flags; - outcurl->progress.callback = data->progress.callback; - - if(data->cookies) { - /* If cookies are enabled in the parent handle, we enable them - in the clone as well! */ - outcurl->cookies = Curl_cookie_init(data, - data->cookies->filename, - outcurl->cookies, - data->set.cookiesession); - if(!outcurl->cookies) - goto fail; - } - - /* duplicate all values in 'change' */ - if(data->change.cookielist) { - outcurl->change.cookielist = - Curl_slist_duplicate(data->change.cookielist); - if(!outcurl->change.cookielist) - goto fail; - } - - if(data->change.url) { - outcurl->change.url = strdup(data->change.url); - if(!outcurl->change.url) - goto fail; - outcurl->change.url_alloc = TRUE; - } - - if(data->change.referer) { - outcurl->change.referer = strdup(data->change.referer); - if(!outcurl->change.referer) - goto fail; - outcurl->change.referer_alloc = TRUE; - } - + + outcurl->progress.flags = data->progress.flags; + outcurl->progress.callback = data->progress.callback; + + if(data->cookies) { + /* If cookies are enabled in the parent handle, we enable them + in the clone as well! */ + outcurl->cookies = Curl_cookie_init(data, + data->cookies->filename, + outcurl->cookies, + data->set.cookiesession); + if(!outcurl->cookies) + goto fail; + } + + /* duplicate all values in 'change' */ + if(data->change.cookielist) { + outcurl->change.cookielist = + Curl_slist_duplicate(data->change.cookielist); + if(!outcurl->change.cookielist) + goto fail; + } + + if(data->change.url) { + outcurl->change.url = strdup(data->change.url); + if(!outcurl->change.url) + goto fail; + outcurl->change.url_alloc = TRUE; + } + + if(data->change.referer) { + outcurl->change.referer = strdup(data->change.referer); + if(!outcurl->change.referer) + goto fail; + outcurl->change.referer_alloc = TRUE; + } + /* Reinitialize an SSL engine for the new handle * note: the engine name has already been copied by dupset */ if(outcurl->set.str[STRING_SSL_ENGINE]) { @@ -893,12 +893,12 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data) (void)Curl_hsts_loadcb(outcurl, outcurl->hsts); } #endif - /* Clone the resolver handle, if present, for the new handle */ + /* Clone the resolver handle, if present, for the new handle */ if(Curl_resolver_duphandle(outcurl, &outcurl->state.resolver, data->state.resolver)) - goto fail; - + goto fail; + #ifdef USE_ARES { CURLcode rc; @@ -921,55 +921,55 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data) } #endif /* USE_ARES */ - Curl_convert_setup(outcurl); - + Curl_convert_setup(outcurl); + Curl_initinfo(outcurl); - outcurl->magic = CURLEASY_MAGIC_NUMBER; - - /* we reach this point and thus we are OK */ - - return outcurl; - - fail: - - if(outcurl) { - curl_slist_free_all(outcurl->change.cookielist); - outcurl->change.cookielist = NULL; + outcurl->magic = CURLEASY_MAGIC_NUMBER; + + /* we reach this point and thus we are OK */ + + return outcurl; + + fail: + + if(outcurl) { + curl_slist_free_all(outcurl->change.cookielist); + outcurl->change.cookielist = NULL; Curl_safefree(outcurl->state.buffer); Curl_dyn_free(&outcurl->state.headerb); - Curl_safefree(outcurl->change.url); - Curl_safefree(outcurl->change.referer); + Curl_safefree(outcurl->change.url); + Curl_safefree(outcurl->change.referer); Curl_altsvc_cleanup(&outcurl->asi); Curl_hsts_cleanup(&outcurl->hsts); - Curl_freeset(outcurl); - free(outcurl); - } - - return NULL; -} - -/* - * curl_easy_reset() is an external interface that allows an app to re- - * initialize a session handle to the default values. - */ + Curl_freeset(outcurl); + free(outcurl); + } + + return NULL; +} + +/* + * curl_easy_reset() is an external interface that allows an app to re- + * initialize a session handle to the default values. + */ void curl_easy_reset(struct Curl_easy *data) -{ - Curl_free_request_state(data); - - /* zero out UserDefined data: */ - Curl_freeset(data); - memset(&data->set, 0, sizeof(struct UserDefined)); +{ + Curl_free_request_state(data); + + /* zero out UserDefined data: */ + Curl_freeset(data); + memset(&data->set, 0, sizeof(struct UserDefined)); (void)Curl_init_userdefined(data); - - /* zero out Progress data: */ - memset(&data->progress, 0, sizeof(struct Progress)); - + + /* zero out Progress data: */ + memset(&data->progress, 0, sizeof(struct Progress)); + /* zero out PureInfo data: */ Curl_initinfo(data); - data->progress.flags |= PGRS_HIDE; - data->state.current_speed = -1; /* init to negative == impossible */ + data->progress.flags |= PGRS_HIDE; + data->state.current_speed = -1; /* init to negative == impossible */ data->state.retrycount = 0; /* reset the retry counter */ /* zero out authentication data: */ @@ -979,40 +979,40 @@ void curl_easy_reset(struct Curl_easy *data) #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH) Curl_http_auth_cleanup_digest(data); #endif -} - -/* - * curl_easy_pause() allows an application to pause or unpause a specific - * transfer and direction. This function sets the full new state for the - * current connection this easy handle operates on. - * - * NOTE: if you have the receiving paused and you call this function to remove - * the pausing, you may get your write callback called at this point. - * - * Action is a bitmask consisting of CURLPAUSE_* bits in curl/curl.h +} + +/* + * curl_easy_pause() allows an application to pause or unpause a specific + * transfer and direction. This function sets the full new state for the + * current connection this easy handle operates on. + * + * NOTE: if you have the receiving paused and you call this function to remove + * the pausing, you may get your write callback called at this point. + * + * Action is a bitmask consisting of CURLPAUSE_* bits in curl/curl.h * * NOTE: This is one of few API functions that are allowed to be called from * within a callback. - */ + */ CURLcode curl_easy_pause(struct Curl_easy *data, int action) -{ +{ struct SingleRequest *k; - CURLcode result = CURLE_OK; + CURLcode result = CURLE_OK; int oldstate; int newstate; - + if(!GOOD_EASY_HANDLE(data) || !data->conn) /* crazy input, don't continue */ return CURLE_BAD_FUNCTION_ARGUMENT; - + k = &data->req; oldstate = k->keepon & (KEEP_RECV_PAUSE| KEEP_SEND_PAUSE); /* first switch off both pause bits then set the new pause bits */ newstate = (k->keepon &~ (KEEP_RECV_PAUSE| KEEP_SEND_PAUSE)) | ((action & CURLPAUSE_RECV)?KEEP_RECV_PAUSE:0) | - ((action & CURLPAUSE_SEND)?KEEP_SEND_PAUSE:0); - + ((action & CURLPAUSE_SEND)?KEEP_SEND_PAUSE:0); + if((newstate & (KEEP_RECV_PAUSE| KEEP_SEND_PAUSE)) == oldstate) { /* Not changing any pause state, return */ DEBUGF(infof(data, "pause: no change, early return\n")); @@ -1027,12 +1027,12 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action) Curl_mime_unpause(data->state.in); } - /* put it back in the keepon */ - k->keepon = newstate; - + /* put it back in the keepon */ + k->keepon = newstate; + if(!(newstate & KEEP_RECV_PAUSE)) { Curl_http2_stream_pause(data, FALSE); - + if(data->state.tempcount) { /* there are buffers for sending that can be delivered as the receive pausing is lifted! */ @@ -1041,20 +1041,20 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action) struct tempbuf writebuf[3]; /* there can only be three */ struct connectdata *conn = data->conn; struct Curl_easy *saved_data = NULL; - + /* copy the structs to allow for immediate re-pausing */ for(i = 0; i < data->state.tempcount; i++) { writebuf[i] = data->state.tempwrite[i]; Curl_dyn_init(&data->state.tempwrite[i].b, DYN_PAUSE_BUFFER); } data->state.tempcount = 0; - + /* set the connection's current owner */ if(conn->data != data) { saved_data = conn->data; conn->data = data; } - + for(i = 0; i < count; i++) { /* even if one function returns error, this loops through and frees all buffers */ @@ -1064,7 +1064,7 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action) Curl_dyn_len(&writebuf[i].b)); Curl_dyn_free(&writebuf[i].b); } - + /* recover previous owner of the connection */ if(saved_data) conn->data = saved_data; @@ -1072,10 +1072,10 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action) if(result) return result; } - } - - /* if there's no error and we're not pausing both directions, we want - to have this handle checked soon */ + } + + /* 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)) != (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) { Curl_expire(data, 0, EXPIRE_RUN_NOW); /* get this handle going again */ @@ -1087,103 +1087,103 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action) if(data->multi) Curl_update_timer(data->multi); } - + if(!data->state.done) /* This transfer may have been moved in or out of the bundle, update the corresponding socket callback, if used */ Curl_updatesocket(data); - return result; -} - - + return result; +} + + static CURLcode easy_connection(struct Curl_easy *data, - curl_socket_t *sfd, - struct connectdata **connp) -{ - if(data == NULL) - return CURLE_BAD_FUNCTION_ARGUMENT; - - /* only allow these to be called on handles with CURLOPT_CONNECT_ONLY */ - if(!data->set.connect_only) { - failf(data, "CONNECT_ONLY is required!"); - return CURLE_UNSUPPORTED_PROTOCOL; - } - - *sfd = Curl_getconnectinfo(data, connp); - - if(*sfd == CURL_SOCKET_BAD) { - failf(data, "Failed to get recent socket"); - return CURLE_UNSUPPORTED_PROTOCOL; - } - - return CURLE_OK; -} - -/* - * Receives data from the connected socket. Use after successful - * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. - * Returns CURLE_OK on success, error code on error. - */ + curl_socket_t *sfd, + struct connectdata **connp) +{ + if(data == NULL) + return CURLE_BAD_FUNCTION_ARGUMENT; + + /* only allow these to be called on handles with CURLOPT_CONNECT_ONLY */ + if(!data->set.connect_only) { + failf(data, "CONNECT_ONLY is required!"); + return CURLE_UNSUPPORTED_PROTOCOL; + } + + *sfd = Curl_getconnectinfo(data, connp); + + if(*sfd == CURL_SOCKET_BAD) { + failf(data, "Failed to get recent socket"); + return CURLE_UNSUPPORTED_PROTOCOL; + } + + return CURLE_OK; +} + +/* + * Receives data from the connected socket. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + * Returns CURLE_OK on success, error code on error. + */ CURLcode curl_easy_recv(struct Curl_easy *data, void *buffer, size_t buflen, size_t *n) -{ - curl_socket_t sfd; +{ + curl_socket_t sfd; CURLcode result; - ssize_t n1; - struct connectdata *c; - + ssize_t n1; + struct connectdata *c; + if(Curl_is_in_callback(data)) return CURLE_RECURSIVE_API_CALL; - + result = easy_connection(data, &sfd, &c); if(result) return result; - *n = 0; + *n = 0; result = Curl_read(c, sfd, buffer, buflen, &n1); - + if(result) return result; - - *n = (size_t)n1; - - return CURLE_OK; -} - -/* - * Sends data over the connected socket. Use after successful - * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. - */ + + *n = (size_t)n1; + + return CURLE_OK; +} + +/* + * 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) -{ - curl_socket_t sfd; +{ + curl_socket_t sfd; CURLcode result; - ssize_t n1; - struct connectdata *c = NULL; - + ssize_t n1; + struct connectdata *c = NULL; + if(Curl_is_in_callback(data)) return CURLE_RECURSIVE_API_CALL; - + result = easy_connection(data, &sfd, &c); if(result) return result; - *n = 0; + *n = 0; result = Curl_write(c, sfd, buffer, buflen, &n1); - - if(n1 == -1) - return CURLE_SEND_ERROR; - - /* detect EAGAIN */ + + if(n1 == -1) + return CURLE_SEND_ERROR; + + /* detect EAGAIN */ if(!result && !n1) - return CURLE_AGAIN; - - *n = (size_t)n1; - + return CURLE_AGAIN; + + *n = (size_t)n1; + return result; -} +} /* * Wrapper to call functions in Curl_conncache_foreach() |