summaryrefslogtreecommitdiff
path: root/libs/libcurl/src/multi.c
diff options
context:
space:
mode:
Diffstat (limited to 'libs/libcurl/src/multi.c')
-rw-r--r--libs/libcurl/src/multi.c388
1 files changed, 64 insertions, 324 deletions
diff --git a/libs/libcurl/src/multi.c b/libs/libcurl/src/multi.c
index b79a577d9e..fa130b23fe 100644
--- a/libs/libcurl/src/multi.c
+++ b/libs/libcurl/src/multi.c
@@ -46,6 +46,7 @@
#include "multihandle.h"
#include "sigpipe.h"
#include "vtls/vtls.h"
+#include "vtls/vtls_scache.h"
#include "http_proxy.h"
#include "http2.h"
#include "socketpair.h"
@@ -59,7 +60,7 @@
/*
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
- CURL handle takes 45-50 K memory, therefore this 3K are not significant.
+ curl handle takes 6K memory, therefore this 3K are not significant.
*/
#ifndef CURL_SOCKET_HASH_TABLE_SIZE
#define CURL_SOCKET_HASH_TABLE_SIZE 911
@@ -73,6 +74,10 @@
#define CURL_DNS_HASH_SIZE 71
#endif
+#ifndef CURL_TLS_SESSION_SIZE
+#define CURL_TLS_SESSION_SIZE 25
+#endif
+
#define CURL_MULTI_HANDLE 0x000bab1e
#ifdef DEBUGBUILD
@@ -395,9 +400,10 @@ static void multi_addmsg(struct Curl_multi *multi, struct Curl_message *msg)
Curl_llist_append(&multi->msglist, msg, &msg->list);
}
-struct Curl_multi *Curl_multi_handle(size_t hashsize, /* socket hash */
+struct Curl_multi *Curl_multi_handle(size_t hashsize, /* socket hash */
size_t chashsize, /* connection hash */
- size_t dnssize) /* dns hash */
+ size_t dnssize, /* dns hash */
+ size_t sesssize) /* TLS session cache */
{
struct Curl_multi *multi = calloc(1, sizeof(struct Curl_multi));
@@ -414,7 +420,10 @@ struct Curl_multi *Curl_multi_handle(size_t hashsize, /* socket hash */
Curl_hash_str, Curl_str_key_compare, ph_freeentry);
if(Curl_cpool_init(&multi->cpool, Curl_on_disconnect,
- multi, NULL, chashsize))
+ multi, NULL, chashsize))
+ goto error;
+
+ if(Curl_ssl_scache_create(sesssize, 2, &multi->ssl_scache))
goto error;
Curl_llist_init(&multi->msglist, NULL);
@@ -447,6 +456,7 @@ error:
Curl_hash_destroy(&multi->proto_hash);
Curl_hash_destroy(&multi->hostcache);
Curl_cpool_destroy(&multi->cpool);
+ Curl_ssl_scache_destroy(multi->ssl_scache);
free(multi);
return NULL;
}
@@ -455,7 +465,8 @@ CURLM *curl_multi_init(void)
{
return Curl_multi_handle(CURL_SOCKET_HASH_TABLE_SIZE,
CURL_CONNECTION_HASH_SIZE,
- CURL_DNS_HASH_SIZE);
+ CURL_DNS_HASH_SIZE,
+ CURL_TLS_SESSION_SIZE);
}
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
@@ -787,7 +798,7 @@ CURLMcode curl_multi_remove_handle(CURLM *m, CURL *d)
return CURLM_BAD_HANDLE;
/* Verify that we got a somewhat good easy handle too */
- if(!GOOD_EASY_HANDLE(data) || !multi->num_easy)
+ if(!GOOD_EASY_HANDLE(data))
return CURLM_BAD_EASY_HANDLE;
/* Prevent users from trying to remove same easy handle more than once */
@@ -798,6 +809,11 @@ CURLMcode curl_multi_remove_handle(CURLM *m, CURL *d)
if(data->multi != multi)
return CURLM_BAD_EASY_HANDLE;
+ if(!multi->num_easy) {
+ DEBUGASSERT(0);
+ return CURLM_INTERNAL_ERROR;
+ }
+
if(multi->in_callback)
return CURLM_RECURSIVE_API_CALL;
@@ -917,7 +933,7 @@ CURLMcode curl_multi_remove_handle(CURLM *m, CURL *d)
/* Return TRUE if the application asked for multiplexing */
bool Curl_multiplex_wanted(const struct Curl_multi *multi)
{
- return (multi && (multi->multiplexing));
+ return multi && multi->multiplexing;
}
/*
@@ -930,7 +946,6 @@ void Curl_detach_connection(struct Curl_easy *data)
{
struct connectdata *conn = data->conn;
if(conn) {
- Curl_conn_ev_data_detach(conn, data);
Curl_node_remove(&data->conn_queue);
}
data->conn = NULL;
@@ -951,7 +966,6 @@ void Curl_attach_connection(struct Curl_easy *data,
Curl_llist_append(&conn->easyq, data, &data->conn_queue);
if(conn->handler && conn->handler->attach)
conn->handler->attach(data, conn);
- Curl_conn_ev_data_attach(conn, data);
}
static int connecting_getsock(struct Curl_easy *data, curl_socket_t *socks)
@@ -1152,6 +1166,7 @@ CURLMcode curl_multi_fdset(CURLM *m,
int this_max_fd = -1;
struct Curl_llist_node *e;
struct Curl_multi *multi = m;
+ unsigned int i;
(void)exc_fd_set; /* not used */
if(!GOOD_MULTI_HANDLE(multi))
@@ -1162,7 +1177,6 @@ CURLMcode curl_multi_fdset(CURLM *m,
for(e = Curl_llist_head(&multi->process); e; e = Curl_node_next(e)) {
struct Curl_easy *data = Curl_node_elem(e);
- unsigned int i;
multi_getsock(data, &data->last_poll);
@@ -1170,15 +1184,24 @@ CURLMcode curl_multi_fdset(CURLM *m,
if(!FDSET_SOCK(data->last_poll.sockets[i]))
/* pretend it does not exist */
continue;
+#if defined(__DJGPP__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Warith-conversion"
+#endif
if(data->last_poll.actions[i] & CURL_POLL_IN)
FD_SET(data->last_poll.sockets[i], read_fd_set);
if(data->last_poll.actions[i] & CURL_POLL_OUT)
FD_SET(data->last_poll.sockets[i], write_fd_set);
+#if defined(__DJGPP__)
+#pragma GCC diagnostic pop
+#endif
if((int)data->last_poll.sockets[i] > this_max_fd)
this_max_fd = (int)data->last_poll.sockets[i];
}
}
+ Curl_cpool_setfds(&multi->cpool, read_fd_set, write_fd_set, &this_max_fd);
+
*max_fd = this_max_fd;
return CURLM_OK;
@@ -1189,12 +1212,13 @@ CURLMcode curl_multi_waitfds(CURLM *m,
unsigned int size,
unsigned int *fd_count)
{
- struct curl_waitfds cwfds;
+ struct Curl_waitfds cwfds;
CURLMcode result = CURLM_OK;
struct Curl_llist_node *e;
struct Curl_multi *multi = m;
+ unsigned int need = 0;
- if(!ufds)
+ if(!ufds && (size || !fd_count))
return CURLM_BAD_FUNCTION_ARGUMENT;
if(!GOOD_MULTI_HANDLE(multi))
@@ -1207,20 +1231,17 @@ CURLMcode curl_multi_waitfds(CURLM *m,
for(e = Curl_llist_head(&multi->process); e; e = Curl_node_next(e)) {
struct Curl_easy *data = Curl_node_elem(e);
multi_getsock(data, &data->last_poll);
- if(Curl_waitfds_add_ps(&cwfds, &data->last_poll)) {
- result = CURLM_OUT_OF_MEMORY;
- goto out;
- }
+ need += Curl_waitfds_add_ps(&cwfds, &data->last_poll);
}
- if(Curl_cpool_add_waitfds(&multi->cpool, &cwfds)) {
+ need += Curl_cpool_add_waitfds(&multi->cpool, &cwfds);
+
+ if(need != cwfds.n && ufds) {
result = CURLM_OUT_OF_MEMORY;
- goto out;
}
-out:
if(fd_count)
- *fd_count = cwfds.n;
+ *fd_count = need;
return result;
}
@@ -1517,15 +1538,6 @@ CURLMcode curl_multi_wakeup(CURLM *m)
Curl_multi struct that are constant */
struct Curl_multi *multi = m;
-#if defined(ENABLE_WAKEUP) && !defined(USE_WINSOCK)
-#ifdef USE_EVENTFD
- const void *buf;
- const uint64_t val = 1;
-#else
- char buf[1];
-#endif
-#endif
-
/* GOOD_MULTI_HANDLE can be safely called */
if(!GOOD_MULTI_HANDLE(multi))
return CURLM_BAD_HANDLE;
@@ -1539,15 +1551,14 @@ CURLMcode curl_multi_wakeup(CURLM *m)
making it safe to access from another thread after the init part
and before cleanup */
if(multi->wakeup_pair[1] != CURL_SOCKET_BAD) {
+ while(1) {
#ifdef USE_EVENTFD
- buf = &val;
- /* eventfd has a stringent rule of requiring the 8-byte buffer when
- calling write(2) on it, which makes the sizeof(buf) below fine since
- this is only used on 64-bit systems and then the pointer is 64-bit */
+ /* eventfd has a stringent rule of requiring the 8-byte buffer when
+ calling write(2) on it */
+ const uint64_t buf[1] = { 1 };
#else
- buf[0] = 1;
+ const char buf[1] = { 1 };
#endif
- while(1) {
/* swrite() is not thread-safe in general, because concurrent calls
can have their messages interleaved, but in this case the content
of the messages does not matter, which makes it ok to call.
@@ -1834,289 +1845,13 @@ static void multi_posttransfer(struct Curl_easy *data)
* This function DOES NOT FREE the given url.
*/
static CURLcode multi_follow(struct Curl_easy *data,
- char *newurl, /* the Location: string */
+ const struct Curl_handler *handler,
+ const char *newurl, /* the Location: string */
followtype type) /* see transfer.h */
{
-#ifdef CURL_DISABLE_HTTP
- (void)data;
- (void)newurl;
- (void)type;
- /* Location: following will not happen when HTTP is disabled */
+ if(handler && handler->follow)
+ return handler->follow(data, newurl, type);
return CURLE_TOO_MANY_REDIRECTS;
-#else
-
- /* Location: redirect */
- bool disallowport = FALSE;
- bool reachedmax = FALSE;
- CURLUcode uc;
-
- DEBUGASSERT(type != FOLLOW_NONE);
-
- if(type != FOLLOW_FAKE)
- data->state.requests++; /* count all real follows */
- if(type == FOLLOW_REDIR) {
- if((data->set.maxredirs != -1) &&
- (data->state.followlocation >= data->set.maxredirs)) {
- reachedmax = TRUE;
- type = FOLLOW_FAKE; /* switch to fake to store the would-be-redirected
- to URL */
- }
- else {
- data->state.followlocation++; /* count redirect-followings, including
- auth reloads */
-
- if(data->set.http_auto_referer) {
- CURLU *u;
- char *referer = NULL;
-
- /* We are asked to automatically set the previous URL as the referer
- when we get the next URL. We pick the ->url field, which may or may
- not be 100% correct */
-
- if(data->state.referer_alloc) {
- Curl_safefree(data->state.referer);
- data->state.referer_alloc = FALSE;
- }
-
- /* Make a copy of the URL without credentials and fragment */
- u = curl_url();
- if(!u)
- return CURLE_OUT_OF_MEMORY;
-
- uc = curl_url_set(u, CURLUPART_URL, data->state.url, 0);
- if(!uc)
- uc = curl_url_set(u, CURLUPART_FRAGMENT, NULL, 0);
- if(!uc)
- uc = curl_url_set(u, CURLUPART_USER, NULL, 0);
- if(!uc)
- uc = curl_url_set(u, CURLUPART_PASSWORD, NULL, 0);
- if(!uc)
- uc = curl_url_get(u, CURLUPART_URL, &referer, 0);
-
- curl_url_cleanup(u);
-
- if(uc || !referer)
- return CURLE_OUT_OF_MEMORY;
-
- data->state.referer = referer;
- data->state.referer_alloc = TRUE; /* yes, free this later */
- }
- }
- }
-
- if((type != FOLLOW_RETRY) &&
- (data->req.httpcode != 401) && (data->req.httpcode != 407) &&
- Curl_is_absolute_url(newurl, NULL, 0, FALSE)) {
- /* If this is not redirect due to a 401 or 407 response and an absolute
- URL: do not allow a custom port number */
- disallowport = TRUE;
- }
-
- DEBUGASSERT(data->state.uh);
- uc = curl_url_set(data->state.uh, CURLUPART_URL, newurl, (unsigned int)
- ((type == FOLLOW_FAKE) ? CURLU_NON_SUPPORT_SCHEME :
- ((type == FOLLOW_REDIR) ? CURLU_URLENCODE : 0) |
- CURLU_ALLOW_SPACE |
- (data->set.path_as_is ? CURLU_PATH_AS_IS : 0)));
- if(uc) {
- if(type != FOLLOW_FAKE) {
- failf(data, "The redirect target URL could not be parsed: %s",
- curl_url_strerror(uc));
- return Curl_uc_to_curlcode(uc);
- }
-
- /* the URL could not be parsed for some reason, but since this is FAKE
- mode, just duplicate the field as-is */
- newurl = strdup(newurl);
- if(!newurl)
- return CURLE_OUT_OF_MEMORY;
- }
- else {
- uc = curl_url_get(data->state.uh, CURLUPART_URL, &newurl, 0);
- if(uc)
- return Curl_uc_to_curlcode(uc);
-
- /* Clear auth if this redirects to a different port number or protocol,
- unless permitted */
- if(!data->set.allow_auth_to_other_hosts && (type != FOLLOW_FAKE)) {
- char *portnum;
- int port;
- bool clear = FALSE;
-
- if(data->set.use_port && data->state.allow_port)
- /* a custom port is used */
- port = (int)data->set.use_port;
- else {
- uc = curl_url_get(data->state.uh, CURLUPART_PORT, &portnum,
- CURLU_DEFAULT_PORT);
- if(uc) {
- free(newurl);
- return Curl_uc_to_curlcode(uc);
- }
- port = atoi(portnum);
- free(portnum);
- }
- if(port != data->info.conn_remote_port) {
- infof(data, "Clear auth, redirects to port from %u to %u",
- data->info.conn_remote_port, port);
- clear = TRUE;
- }
- else {
- char *scheme;
- const struct Curl_handler *p;
- uc = curl_url_get(data->state.uh, CURLUPART_SCHEME, &scheme, 0);
- if(uc) {
- free(newurl);
- return Curl_uc_to_curlcode(uc);
- }
-
- p = Curl_get_scheme_handler(scheme);
- if(p && (p->protocol != data->info.conn_protocol)) {
- infof(data, "Clear auth, redirects scheme from %s to %s",
- data->info.conn_scheme, scheme);
- clear = TRUE;
- }
- free(scheme);
- }
- if(clear) {
- Curl_safefree(data->state.aptr.user);
- Curl_safefree(data->state.aptr.passwd);
- }
- }
- }
-
- if(type == FOLLOW_FAKE) {
- /* we are only figuring out the new URL if we would have followed locations
- but now we are done so we can get out! */
- data->info.wouldredirect = newurl;
-
- if(reachedmax) {
- failf(data, "Maximum (%ld) redirects followed", data->set.maxredirs);
- return CURLE_TOO_MANY_REDIRECTS;
- }
- return CURLE_OK;
- }
-
- if(disallowport)
- data->state.allow_port = FALSE;
-
- if(data->state.url_alloc)
- Curl_safefree(data->state.url);
-
- data->state.url = newurl;
- data->state.url_alloc = TRUE;
- Curl_req_soft_reset(&data->req, data);
- infof(data, "Issue another request to this URL: '%s'", data->state.url);
-
- /*
- * We get here when the HTTP code is 300-399 (and 401). We need to perform
- * differently based on exactly what return code there was.
- *
- * News from 7.10.6: we can also get here on a 401 or 407, in case we act on
- * an HTTP (proxy-) authentication scheme other than Basic.
- */
- switch(data->info.httpcode) {
- /* 401 - Act on a WWW-Authenticate, we keep on moving and do the
- Authorization: XXXX header in the HTTP request code snippet */
- /* 407 - Act on a Proxy-Authenticate, we keep on moving and do the
- Proxy-Authorization: XXXX header in the HTTP request code snippet */
- /* 300 - Multiple Choices */
- /* 306 - Not used */
- /* 307 - Temporary Redirect */
- default: /* for all above (and the unknown ones) */
- /* Some codes are explicitly mentioned since I have checked RFC2616 and
- * they seem to be OK to POST to.
- */
- break;
- case 301: /* Moved Permanently */
- /* (quote from RFC7231, section 6.4.2)
- *
- * Note: For historical reasons, a user agent MAY change the request
- * method from POST to GET for the subsequent request. If this
- * behavior is undesired, the 307 (Temporary Redirect) status code
- * can be used instead.
- *
- * ----
- *
- * Many webservers expect this, so these servers often answers to a POST
- * request with an error page. To be sure that libcurl gets the page that
- * most user agents would get, libcurl has to force GET.
- *
- * This behavior is forbidden by RFC1945 and the obsolete RFC2616, and
- * can be overridden with CURLOPT_POSTREDIR.
- */
- if((data->state.httpreq == HTTPREQ_POST
- || data->state.httpreq == HTTPREQ_POST_FORM
- || data->state.httpreq == HTTPREQ_POST_MIME)
- && !(data->set.keep_post & CURL_REDIR_POST_301)) {
- infof(data, "Switch from POST to GET");
- data->state.httpreq = HTTPREQ_GET;
- Curl_creader_set_rewind(data, FALSE);
- }
- break;
- case 302: /* Found */
- /* (quote from RFC7231, section 6.4.3)
- *
- * Note: For historical reasons, a user agent MAY change the request
- * method from POST to GET for the subsequent request. If this
- * behavior is undesired, the 307 (Temporary Redirect) status code
- * can be used instead.
- *
- * ----
- *
- * Many webservers expect this, so these servers often answers to a POST
- * request with an error page. To be sure that libcurl gets the page that
- * most user agents would get, libcurl has to force GET.
- *
- * This behavior is forbidden by RFC1945 and the obsolete RFC2616, and
- * can be overridden with CURLOPT_POSTREDIR.
- */
- if((data->state.httpreq == HTTPREQ_POST
- || data->state.httpreq == HTTPREQ_POST_FORM
- || data->state.httpreq == HTTPREQ_POST_MIME)
- && !(data->set.keep_post & CURL_REDIR_POST_302)) {
- infof(data, "Switch from POST to GET");
- data->state.httpreq = HTTPREQ_GET;
- Curl_creader_set_rewind(data, FALSE);
- }
- break;
-
- case 303: /* See Other */
- /* 'See Other' location is not the resource but a substitute for the
- * resource. In this case we switch the method to GET/HEAD, unless the
- * method is POST and the user specified to keep it as POST.
- * https://github.com/curl/curl/issues/5237#issuecomment-614641049
- */
- if(data->state.httpreq != HTTPREQ_GET &&
- ((data->state.httpreq != HTTPREQ_POST &&
- data->state.httpreq != HTTPREQ_POST_FORM &&
- data->state.httpreq != HTTPREQ_POST_MIME) ||
- !(data->set.keep_post & CURL_REDIR_POST_303))) {
- data->state.httpreq = HTTPREQ_GET;
- infof(data, "Switch to %s",
- data->req.no_body ? "HEAD" : "GET");
- }
- break;
- case 304: /* Not Modified */
- /* 304 means we did a conditional request and it was "Not modified".
- * We should not get any Location: header in this response!
- */
- break;
- case 305: /* Use Proxy */
- /* (quote from RFC2616, section 10.3.6):
- * "The requested resource MUST be accessed through the proxy given
- * by the Location field. The Location field gives the URI of the
- * proxy. The recipient is expected to repeat this single request
- * via the proxy. 305 responses MUST only be generated by origin
- * servers."
- */
- break;
- }
- Curl_pgrsTime(data, TIMER_REDIRECT);
- Curl_pgrsResetTransferSizes(data);
-
- return CURLE_OK;
-#endif /* CURL_DISABLE_HTTP */
}
static CURLMcode state_performing(struct Curl_easy *data,
@@ -2215,6 +1950,7 @@ static CURLMcode state_performing(struct Curl_easy *data,
multi_done(data, result, TRUE);
}
else if(data->req.done && !Curl_cwriter_is_paused(data)) {
+ const struct Curl_handler *handler = data->conn->handler;
/* call this even if the readwrite function returned error */
multi_posttransfer(data);
@@ -2235,7 +1971,7 @@ static CURLMcode state_performing(struct Curl_easy *data,
follow = FOLLOW_RETRY;
(void)multi_done(data, CURLE_OK, FALSE);
/* multi_done() might return CURLE_GOT_NOTHING */
- result = multi_follow(data, newurl, follow);
+ result = multi_follow(data, handler, newurl, follow);
if(!result) {
multistate(data, MSTATE_SETUP);
rc = CURLM_CALL_MULTI_PERFORM;
@@ -2250,7 +1986,7 @@ static CURLMcode state_performing(struct Curl_easy *data,
free(newurl);
newurl = data->req.location;
data->req.location = NULL;
- result = multi_follow(data, newurl, FOLLOW_FAKE);
+ result = multi_follow(data, handler, newurl, FOLLOW_FAKE);
if(result) {
*stream_errorp = TRUE;
result = multi_done(data, result, TRUE);
@@ -2302,7 +2038,7 @@ static CURLMcode state_do(struct Curl_easy *data,
}
}
- if(data->set.connect_only == 1) {
+ if(data->set.connect_only && !data->set.connect_only_ws) {
/* keep connection open for application to use the socket */
connkeep(data->conn, "CONNECT_ONLY");
multistate(data, MSTATE_DONE);
@@ -2359,6 +2095,7 @@ static CURLMcode state_do(struct Curl_easy *data,
* unexpectedly died. If possible, send the connection back to the
* CONNECT phase so we can try again.
*/
+ const struct Curl_handler *handler = data->conn->handler;
char *newurl = NULL;
followtype follow = FOLLOW_NONE;
CURLcode drc;
@@ -2378,7 +2115,7 @@ static CURLMcode state_do(struct Curl_easy *data,
if(newurl) {
if(!drc || (drc == CURLE_SEND_ERROR)) {
follow = FOLLOW_RETRY;
- drc = multi_follow(data, newurl, follow);
+ drc = multi_follow(data, handler, newurl, follow);
if(!drc) {
multistate(data, MSTATE_SETUP);
rc = CURLM_CALL_MULTI_PERFORM;
@@ -3021,9 +2758,11 @@ CURLMcode curl_multi_perform(CURLM *m, int *running_handles)
sigpipe_apply(multi->cpool.idata, &pipe_st);
Curl_cpool_multi_perform(multi);
-
sigpipe_restore(&pipe_st);
+ if(multi_ischanged(m, TRUE))
+ process_pending_handles(m);
+
/*
* Simply remove all expired timers from the splay since handles are dealt
* with unconditionally by this function and curl_multi_timeout() requires
@@ -3124,6 +2863,7 @@ CURLMcode curl_multi_cleanup(CURLM *m)
Curl_hash_destroy(&multi->proto_hash);
Curl_hash_destroy(&multi->hostcache);
Curl_psl_destroy(&multi->psl);
+ Curl_ssl_scache_destroy(multi->ssl_scache);
#ifdef USE_WINSOCK
WSACloseEvent(multi->wsa_event);
@@ -3619,6 +3359,9 @@ out:
}
sigpipe_restore(&mrc.pipe_st);
+ if(multi_ischanged(multi, TRUE))
+ process_pending_handles(multi);
+
if(running_handles)
*running_handles = (int)multi->num_alive;
@@ -3676,9 +3419,6 @@ CURLMcode curl_multi_setopt(CURLM *m,
break;
case CURLMOPT_MAX_TOTAL_CONNECTIONS:
multi->max_total_connections = va_arg(param, long);
- /* for now, let this also decide the max number of connections
- * in shutdown handling */
- multi->max_shutdown_connections = va_arg(param, long);
break;
/* options formerly used for pipelining */
case CURLMOPT_MAX_PIPELINE_LENGTH:
@@ -4126,7 +3866,7 @@ void Curl_set_in_callback(struct Curl_easy *data, bool value)
bool Curl_is_in_callback(struct Curl_easy *data)
{
- return (data && data->multi && data->multi->in_callback);
+ return data && data->multi && data->multi->in_callback;
}
unsigned int Curl_multi_max_concurrent_streams(struct Curl_multi *multi)