summaryrefslogtreecommitdiffstats
path: root/Utilities/cmcurl/lib/asyn-thread.c
diff options
context:
space:
mode:
Diffstat (limited to 'Utilities/cmcurl/lib/asyn-thread.c')
-rw-r--r--Utilities/cmcurl/lib/asyn-thread.c136
1 files changed, 89 insertions, 47 deletions
diff --git a/Utilities/cmcurl/lib/asyn-thread.c b/Utilities/cmcurl/lib/asyn-thread.c
index 55e0811..68dcbb3 100644
--- a/Utilities/cmcurl/lib/asyn-thread.c
+++ b/Utilities/cmcurl/lib/asyn-thread.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * 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
@@ -21,6 +21,7 @@
***************************************************************************/
#include "curl_setup.h"
+#include "socketpair.h"
/***********************************************************************
* Only for threaded name resolves builds
@@ -70,10 +71,10 @@
#include "strerror.h"
#include "url.h"
#include "multiif.h"
-#include "inet_pton.h"
#include "inet_ntop.h"
#include "curl_threads.h"
#include "connect.h"
+#include "socketpair.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@@ -163,6 +164,10 @@ struct thread_sync_data {
char *hostname; /* hostname to resolve, Curl_async.hostname
duplicate */
int port;
+#ifdef USE_SOCKETPAIR
+ struct connectdata *conn;
+ curl_socket_t sock_pair[2]; /* socket pair */
+#endif
int sock_error;
Curl_addrinfo *res;
#ifdef HAVE_GETADDRINFO
@@ -197,6 +202,15 @@ void destroy_thread_sync_data(struct thread_sync_data * tsd)
if(tsd->res)
Curl_freeaddrinfo(tsd->res);
+#ifdef USE_SOCKETPAIR
+ /*
+ * close one end of the socket pair (may be done in resolver thread);
+ * the other end (for reading) is always closed in the parent thread.
+ */
+ if(tsd->sock_pair[1] != CURL_SOCKET_BAD) {
+ sclose(tsd->sock_pair[1]);
+ }
+#endif
memset(tsd, 0, sizeof(*tsd));
}
@@ -230,6 +244,14 @@ int init_thread_sync_data(struct thread_data * td,
Curl_mutex_init(tsd->mtx);
+#ifdef USE_SOCKETPAIR
+ /* create socket pair, avoid AF_LOCAL since it doesn't build on Solaris */
+ if(Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, &tsd->sock_pair[0]) < 0) {
+ tsd->sock_pair[0] = CURL_SOCKET_BAD;
+ tsd->sock_pair[1] = CURL_SOCKET_BAD;
+ goto err_exit;
+ }
+#endif
tsd->sock_error = CURL_ASYNC_SUCCESS;
/* Copying hostname string because original can be destroyed by parent
@@ -276,6 +298,9 @@ static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg)
struct thread_data *td = tsd->td;
char service[12];
int rc;
+#ifdef USE_SOCKETPAIR
+ char buf[1];
+#endif
msnprintf(service, sizeof(service), "%d", tsd->port);
@@ -298,6 +323,16 @@ static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg)
free(td);
}
else {
+#ifdef USE_SOCKETPAIR
+ if(tsd->sock_pair[1] != CURL_SOCKET_BAD) {
+ /* DNS has been resolved, signal client task */
+ buf[0] = 1;
+ if(swrite(tsd->sock_pair[1], buf, sizeof(buf)) < 0) {
+ /* update sock_erro to errno */
+ tsd->sock_error = SOCKERRNO;
+ }
+ }
+#endif
tsd->done = 1;
Curl_mutex_release(tsd->mtx);
}
@@ -348,6 +383,10 @@ static void destroy_async_data(struct Curl_async *async)
if(async->os_specific) {
struct thread_data *td = (struct thread_data*) async->os_specific;
int done;
+#ifdef USE_SOCKETPAIR
+ curl_socket_t sock_rd = td->tsd.sock_pair[0];
+ struct connectdata *conn = td->tsd.conn;
+#endif
/*
* if the thread is still blocking in the resolve syscall, detach it and
@@ -369,6 +408,15 @@ static void destroy_async_data(struct Curl_async *async)
free(async->os_specific);
}
+#ifdef USE_SOCKETPAIR
+ /*
+ * ensure CURLMOPT_SOCKETFUNCTION fires CURL_POLL_REMOVE
+ * before the FD is invalidated to avoid EBADF on EPOLL_CTL_DEL
+ */
+ if(conn)
+ Curl_multi_closed(conn->data, sock_rd);
+ sclose(sock_rd);
+#endif
}
async->os_specific = NULL;
@@ -569,8 +617,9 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
}
else {
/* poll for name lookup done with exponential backoff up to 250ms */
- timediff_t elapsed = Curl_timediff(Curl_now(),
- data->progress.t_startsingle);
+ /* should be fine even if this converts to 32 bit */
+ time_t elapsed = (time_t)Curl_timediff(Curl_now(),
+ data->progress.t_startsingle);
if(elapsed < 0)
elapsed = 0;
@@ -592,26 +641,45 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
}
int Curl_resolver_getsock(struct connectdata *conn,
- curl_socket_t *socks,
- int numsocks)
+ curl_socket_t *socks)
{
+ int ret_val = 0;
time_t milli;
timediff_t ms;
struct Curl_easy *data = conn->data;
struct resdata *reslv = (struct resdata *)data->state.resolver;
+#ifdef USE_SOCKETPAIR
+ struct thread_data *td = (struct thread_data*)conn->async.os_specific;
+#else
(void)socks;
- (void)numsocks;
- ms = Curl_timediff(Curl_now(), reslv->start);
- if(ms < 3)
- milli = 0;
- else if(ms <= 50)
- milli = ms/3;
- else if(ms <= 250)
- milli = 50;
- else
- milli = 200;
- Curl_expire(data, milli, EXPIRE_ASYNC_NAME);
- return 0;
+#endif
+
+#ifdef USE_SOCKETPAIR
+ if(td) {
+ /* return read fd to client for polling the DNS resolution status */
+ socks[0] = td->tsd.sock_pair[0];
+ DEBUGASSERT(td->tsd.conn == conn || !td->tsd.conn);
+ td->tsd.conn = conn;
+ ret_val = GETSOCK_READSOCK(0);
+ }
+ else {
+#endif
+ ms = Curl_timediff(Curl_now(), reslv->start);
+ if(ms < 3)
+ milli = 0;
+ else if(ms <= 50)
+ milli = (time_t)ms/3;
+ else if(ms <= 250)
+ milli = 50;
+ else
+ milli = 200;
+ Curl_expire(data, milli, EXPIRE_ASYNC_NAME);
+#ifdef USE_SOCKETPAIR
+ }
+#endif
+
+
+ return ret_val;
}
#ifndef HAVE_GETADDRINFO
@@ -623,16 +691,11 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
int port,
int *waitp)
{
- struct in_addr in;
struct Curl_easy *data = conn->data;
struct resdata *reslv = (struct resdata *)data->state.resolver;
*waitp = 0; /* default to synchronous response */
- if(Curl_inet_pton(AF_INET, hostname, &in) > 0)
- /* This is a dotted IP address 123.123.123.123-style */
- return Curl_ip2addr(AF_INET, &in, hostname, port);
-
reslv->start = Curl_now();
/* fire up a new resolver thread! */
@@ -657,32 +720,12 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
int *waitp)
{
struct addrinfo hints;
- char sbuf[12];
int pf = PF_INET;
struct Curl_easy *data = conn->data;
struct resdata *reslv = (struct resdata *)data->state.resolver;
*waitp = 0; /* default to synchronous response */
-#ifndef USE_RESOLVE_ON_IPS
- {
- struct in_addr in;
- /* First check if this is an IPv4 address string */
- if(Curl_inet_pton(AF_INET, hostname, &in) > 0)
- /* This is a dotted IP address 123.123.123.123-style */
- return Curl_ip2addr(AF_INET, &in, hostname, port);
- }
-#ifdef CURLRES_IPV6
- {
- struct in6_addr in6;
- /* check if this is an IPv6 address string */
- if(Curl_inet_pton(AF_INET6, hostname, &in6) > 0)
- /* This is an IPv6 address literal */
- return Curl_ip2addr(AF_INET6, &in6, hostname, port);
- }
-#endif /* CURLRES_IPV6 */
-#endif /* !USE_RESOLVE_ON_IPS */
-
#ifdef CURLRES_IPV6
/*
* Check if a limited name resolve has been requested.
@@ -699,16 +742,15 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
break;
}
- if((pf != PF_INET) && !Curl_ipv6works())
+ if((pf != PF_INET) && !Curl_ipv6works(conn))
/* The stack seems to be a non-IPv6 one */
pf = PF_INET;
#endif /* CURLRES_IPV6 */
memset(&hints, 0, sizeof(hints));
hints.ai_family = pf;
- hints.ai_socktype = conn->socktype;
-
- msnprintf(sbuf, sizeof(sbuf), "%d", port);
+ hints.ai_socktype = (conn->transport == TRNSPRT_TCP)?
+ SOCK_STREAM : SOCK_DGRAM;
reslv->start = Curl_now();
/* fire up a new resolver thread! */