summaryrefslogtreecommitdiffstats
path: root/Utilities/cmcurl/lib/multi.c
diff options
context:
space:
mode:
Diffstat (limited to 'Utilities/cmcurl/lib/multi.c')
-rw-r--r--Utilities/cmcurl/lib/multi.c90
1 files changed, 68 insertions, 22 deletions
diff --git a/Utilities/cmcurl/lib/multi.c b/Utilities/cmcurl/lib/multi.c
index 8e58d78..51acba7 100644
--- a/Utilities/cmcurl/lib/multi.c
+++ b/Utilities/cmcurl/lib/multi.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"
@@ -43,7 +45,6 @@
#include "multihandle.h"
#include "sigpipe.h"
#include "vtls/vtls.h"
-#include "connect.h"
#include "http_proxy.h"
#include "http2.h"
#include "socketpair.h"
@@ -53,6 +54,22 @@
#include "curl_memory.h"
#include "memdebug.h"
+#ifdef __APPLE__
+
+#define wakeup_write write
+#define wakeup_read read
+#define wakeup_close close
+#define wakeup_create pipe
+
+#else /* __APPLE__ */
+
+#define wakeup_write swrite
+#define wakeup_read sread
+#define wakeup_close sclose
+#define wakeup_create(p) Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, p)
+
+#endif /* __APPLE__ */
+
/*
CURL_SOCKET_HASH_TABLE_SIZE should be a prime number. Increasing it from 97
to 911 takes on a 32-bit machine 4 x 804 = 3211 more bytes. Still, every
@@ -66,6 +83,10 @@
#define CURL_CONNECTION_HASH_SIZE 97
#endif
+#ifndef CURL_DNS_HASH_SIZE
+#define CURL_DNS_HASH_SIZE 71
+#endif
+
#define CURL_MULTI_HANDLE 0x000bab1e
#define GOOD_MULTI_HANDLE(x) \
@@ -370,7 +391,8 @@ static CURLMcode multi_addmsg(struct Curl_multi *multi,
}
struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
- int chashsize) /* connection hash */
+ int chashsize, /* connection hash */
+ int dnssize) /* dns hash */
{
struct Curl_multi *multi = calloc(1, sizeof(struct Curl_multi));
@@ -379,7 +401,7 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
multi->magic = CURL_MULTI_HANDLE;
- Curl_init_dnscache(&multi->hostcache);
+ Curl_init_dnscache(&multi->hostcache, dnssize);
sh_init(&multi->sockhash, hashsize);
@@ -394,7 +416,6 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
/* -1 means it not set by user, use the default value */
multi->maxconnects = -1;
multi->max_concurrent_streams = 100;
- multi->ipv6_works = Curl_ipv6works(NULL);
#ifdef USE_WINSOCK
multi->wsa_event = WSACreateEvent();
@@ -402,14 +423,14 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
goto error;
#else
#ifdef ENABLE_WAKEUP
- if(Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, multi->wakeup_pair) < 0) {
+ if(wakeup_create(multi->wakeup_pair) < 0) {
multi->wakeup_pair[0] = CURL_SOCKET_BAD;
multi->wakeup_pair[1] = CURL_SOCKET_BAD;
}
else if(curlx_nonblock(multi->wakeup_pair[0], TRUE) < 0 ||
curlx_nonblock(multi->wakeup_pair[1], TRUE) < 0) {
- sclose(multi->wakeup_pair[0]);
- sclose(multi->wakeup_pair[1]);
+ wakeup_close(multi->wakeup_pair[0]);
+ wakeup_close(multi->wakeup_pair[1]);
multi->wakeup_pair[0] = CURL_SOCKET_BAD;
multi->wakeup_pair[1] = CURL_SOCKET_BAD;
}
@@ -433,7 +454,8 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
struct Curl_multi *curl_multi_init(void)
{
return Curl_multi_handle(CURL_SOCKET_HASH_TABLE_SIZE,
- CURL_CONNECTION_HASH_SIZE);
+ CURL_CONNECTION_HASH_SIZE,
+ CURL_DNS_HASH_SIZE);
}
CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
@@ -627,7 +649,7 @@ static CURLcode multi_done(struct Curl_easy *data,
if(CURLE_ABORTED_BY_CALLBACK != result) {
/* avoid this if we already aborted by callback to avoid this calling
another callback */
- CURLcode rc = Curl_pgrsDone(data);
+ int rc = Curl_pgrsDone(data);
if(!result && rc)
result = CURLE_ABORTED_BY_CALLBACK;
}
@@ -729,7 +751,7 @@ static int close_connect_only(struct Curl_easy *data,
if(data->state.lastconnect_id != conn->connection_id)
return 0;
- if(!conn->bits.connect_only)
+ if(!conn->connect_only)
return 1;
connclose(conn, "Removing connect-only easy handle");
@@ -826,6 +848,24 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
/* Remove the association between the connection and the handle */
Curl_detach_connection(data);
+ if(data->set.connect_only && !data->multi_easy) {
+ /* This removes a handle that was part the multi interface that used
+ CONNECT_ONLY, that connection is now left alive but since this handle
+ has bits.close set nothing can use that transfer anymore and it is
+ forbidden from reuse. And this easy handle cannot find the connection
+ anymore once removed from the multi handle
+
+ Better close the connection here, at once.
+ */
+ struct connectdata *c;
+ curl_socket_t s;
+ s = Curl_getconnectinfo(data, &c);
+ if((s != CURL_SOCKET_BAD) && c) {
+ Curl_conncache_remove_conn(data, c, TRUE);
+ Curl_disconnect(data, c, TRUE);
+ }
+ }
+
if(data->state.lastconnect_id != -1) {
/* Mark any connect-only connection for closure */
Curl_conncache_foreach(data, data->state.conn_cache,
@@ -1307,16 +1347,19 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
pollrc = Curl_poll(ufds, nfds, 0); /* just pre-check with WinSock */
else
pollrc = 0;
- if(pollrc <= 0) /* now wait... if not ready during the pre-check above */
- WSAWaitForMultipleEvents(1, &multi->wsa_event, FALSE, timeout_ms, FALSE);
#else
pollrc = Curl_poll(ufds, nfds, timeout_ms); /* wait... */
#endif
+ if(pollrc < 0)
+ return CURLM_UNRECOVERABLE_POLL;
if(pollrc > 0) {
retcode = pollrc;
#ifdef USE_WINSOCK
}
+ else { /* now wait... if not ready during the pre-check (pollrc == 0) */
+ WSAWaitForMultipleEvents(1, &multi->wsa_event, FALSE, timeout_ms, FALSE);
+ }
/* With WinSock, we have to run the following section unconditionally
to call WSAEventSelect(fd, event, 0) on all the sockets */
{
@@ -1328,20 +1371,23 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
unsigned r = ufds[curlfds + i].revents;
unsigned short mask = 0;
#ifdef USE_WINSOCK
+ curl_socket_t s = extra_fds[i].fd;
wsa_events.lNetworkEvents = 0;
- if(WSAEnumNetworkEvents(extra_fds[i].fd, NULL, &wsa_events) == 0) {
+ if(WSAEnumNetworkEvents(s, NULL, &wsa_events) == 0) {
if(wsa_events.lNetworkEvents & (FD_READ|FD_ACCEPT|FD_CLOSE))
mask |= CURL_WAIT_POLLIN;
if(wsa_events.lNetworkEvents & (FD_WRITE|FD_CONNECT|FD_CLOSE))
mask |= CURL_WAIT_POLLOUT;
if(wsa_events.lNetworkEvents & FD_OOB)
mask |= CURL_WAIT_POLLPRI;
- if(ret && pollrc <= 0 && wsa_events.lNetworkEvents)
+ if(ret && !pollrc && wsa_events.lNetworkEvents)
retcode++;
}
- WSAEventSelect(extra_fds[i].fd, multi->wsa_event, 0);
- if(pollrc <= 0)
+ WSAEventSelect(s, multi->wsa_event, 0);
+ if(!pollrc) {
+ extra_fds[i].revents = mask;
continue;
+ }
#endif
if(r & POLLIN)
mask |= CURL_WAIT_POLLIN;
@@ -1364,7 +1410,7 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
if(bitmap & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i))) {
wsa_events.lNetworkEvents = 0;
if(WSAEnumNetworkEvents(sockbunch[i], NULL, &wsa_events) == 0) {
- if(ret && pollrc <= 0 && wsa_events.lNetworkEvents)
+ if(ret && !pollrc && wsa_events.lNetworkEvents)
retcode++;
}
WSAEventSelect(sockbunch[i], multi->wsa_event, 0);
@@ -1391,7 +1437,7 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
data from it until it receives an error (except EINTR).
In normal cases it will get EAGAIN or EWOULDBLOCK
when there is no more data, breaking the loop. */
- nread = sread(multi->wakeup_pair[0], buf, sizeof(buf));
+ nread = wakeup_read(multi->wakeup_pair[0], buf, sizeof(buf));
if(nread <= 0) {
if(nread < 0 && EINTR == SOCKERRNO)
continue;
@@ -1484,7 +1530,7 @@ CURLMcode curl_multi_wakeup(struct Curl_multi *multi)
that will call curl_multi_wait(). If swrite() returns that it
would block, it's considered successful because it means that
previous calls to this function will wake up the poll(). */
- if(swrite(multi->wakeup_pair[1], buf, sizeof(buf)) < 0) {
+ if(wakeup_write(multi->wakeup_pair[1], buf, sizeof(buf)) < 0) {
int err = SOCKERRNO;
int return_success;
#ifdef USE_WINSOCK
@@ -2096,7 +2142,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
}
}
- if(data->set.connect_only) {
+ if(data->set.connect_only == 1) {
/* keep connection open for application to use the socket */
connkeep(data->conn, "CONNECT_ONLY");
multistate(data, MSTATE_DONE);
@@ -2720,8 +2766,8 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
WSACloseEvent(multi->wsa_event);
#else
#ifdef ENABLE_WAKEUP
- sclose(multi->wakeup_pair[0]);
- sclose(multi->wakeup_pair[1]);
+ wakeup_close(multi->wakeup_pair[0]);
+ wakeup_close(multi->wakeup_pair[1]);
#endif
#endif
free(multi);