curl: add --parallel-max-host to limit concurrent connections per host

Where 'host' is protocol + hostname + portnumber.

Closes #18052
This commit is contained in:
Daniel Stenberg 2025-07-28 10:41:20 +02:00
parent e688fe18a9
commit 4654493fed
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
10 changed files with 56 additions and 3 deletions

View file

@ -357,6 +357,7 @@ struct GlobalConfig {
many milliseconds */
trace tracetype;
int progressmode; /* CURL_PROGRESS_BAR / CURL_PROGRESS_STATS */
unsigned short parallel_host; /* MAX_PARALLEL_HOST is the maximum */
unsigned short parallel_max; /* MAX_PARALLEL is the maximum */
unsigned char verbosity; /* How verbose we should be */
#ifdef DEBUGBUILD

View file

@ -230,6 +230,7 @@ static const struct LongShort aliases[]= {
{"parallel", ARG_BOOL, 'Z', C_PARALLEL},
{"parallel-immediate", ARG_BOOL, ' ', C_PARALLEL_IMMEDIATE},
{"parallel-max", ARG_STRG, ' ', C_PARALLEL_MAX},
{"parallel-max-host", ARG_STRG, ' ', C_PARALLEL_HOST},
{"pass", ARG_STRG|ARG_CLEAR, ' ', C_PASS},
{"path-as-is", ARG_BOOL, ' ', C_PATH_AS_IS},
{"pinnedpubkey", ARG_STRG|ARG_TLS, ' ', C_PINNEDPUBKEY},
@ -2179,6 +2180,7 @@ static ParameterError opt_filestring(struct OperationConfig *config,
{
ParameterError err = PARAM_OK;
curl_off_t value;
long val;
struct GlobalConfig *global = config->global;
static const char *redir_protos[] = {
"http",
@ -2788,8 +2790,19 @@ static ParameterError opt_filestring(struct OperationConfig *config,
if(!err && !config->low_speed_time)
config->low_speed_time = 30;
break;
case C_PARALLEL_MAX: { /* --parallel-max */
long val;
case C_PARALLEL_HOST: /* --parallel-max-host */
err = str2unum(&val, nextarg);
if(err)
break;
if(val > MAX_PARALLEL_HOST)
global->parallel_host = MAX_PARALLEL_HOST;
else if(val < 1)
global->parallel_host = PARALLEL_HOST_DEFAULT;
else
global->parallel_host = (unsigned short)val;
break;
break;
case C_PARALLEL_MAX: /* --parallel-max */
err = str2unum(&val, nextarg);
if(err)
break;
@ -2800,7 +2813,6 @@ static ParameterError opt_filestring(struct OperationConfig *config,
else
global->parallel_max = (unsigned short)val;
break;
}
case C_TIME_COND: /* --time-cond */
err = parse_time_cond(config, nextarg);
break;

View file

@ -171,6 +171,7 @@ typedef enum {
C_OUTPUT,
C_OUTPUT_DIR,
C_PARALLEL,
C_PARALLEL_HOST,
C_PARALLEL_IMMEDIATE,
C_PARALLEL_MAX,
C_PASS,

View file

@ -460,6 +460,9 @@ const struct helptxt helptext[] = {
{" --parallel-max <num>",
"Maximum concurrency for parallel transfers",
CURLHELP_CONNECTION | CURLHELP_CURL | CURLHELP_GLOBAL},
{" --parallel-max-host <num>",
"Maximum connections to a single host",
CURLHELP_CONNECTION | CURLHELP_CURL | CURLHELP_GLOBAL},
{" --pass <phrase>",
"Passphrase for the private key",
CURLHELP_SSH | CURLHELP_TLS | CURLHELP_AUTH},

View file

@ -33,4 +33,7 @@
#define MAX_PARALLEL 65535
#define PARALLEL_DEFAULT 50
#define MAX_PARALLEL_HOST 65535
#define PARALLEL_HOST_DEFAULT 0 /* means not used */
#endif /* HEADER_CURL_TOOL_MAIN_H */

View file

@ -1689,6 +1689,8 @@ static CURLcode parallel_event(struct parastate *s)
curl_multi_setopt(s->multi, CURLMOPT_SOCKETDATA, &uv);
curl_multi_setopt(s->multi, CURLMOPT_TIMERFUNCTION, cb_timeout);
curl_multi_setopt(s->multi, CURLMOPT_TIMERDATA, &uv);
curl_multi_setopt(s->multi, CURLMOPT_MAX_HOST_CONNECTIONS,
s->global->parallel_host);
/* kickstart the thing */
curl_multi_socket_action(s->multi, CURL_SOCKET_TIMEOUT, 0,