aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/config/http.adoc18
-rw-r--r--git-curl-compat.h7
-rw-r--r--http.c75
3 files changed, 84 insertions, 16 deletions
diff --git a/Documentation/config/http.adoc b/Documentation/config/http.adoc
index 22a8803dea..67393282fa 100644
--- a/Documentation/config/http.adoc
+++ b/Documentation/config/http.adoc
@@ -296,6 +296,24 @@ http.lowSpeedLimit, http.lowSpeedTime::
Can be overridden by the `GIT_HTTP_LOW_SPEED_LIMIT` and
`GIT_HTTP_LOW_SPEED_TIME` environment variables.
+http.keepAliveIdle::
+ Specifies how long in seconds to wait on an idle connection
+ before sending TCP keepalive probes (if supported by the OS). If
+ unset, curl's default value is used. Can be overridden by the
+ `GIT_HTTP_KEEPALIVE_IDLE` environment variable.
+
+http.keepAliveInterval::
+ Specifies how long in seconds to wait between TCP keepalive
+ probes (if supported by the OS). If unset, curl's default value
+ is used. Can be overridden by the `GIT_HTTP_KEEPALIVE_INTERVAL`
+ environment variable.
+
+http.keepAliveCount::
+ Specifies how many TCP keepalive probes to send before giving up
+ and terminating the connection (if supported by the OS). If
+ unset, curl's default value is used. Can be overridden by the
+ `GIT_HTTP_KEEPALIVE_COUNT` environment variable.
+
http.noEPSV::
A boolean which disables using of EPSV ftp command by curl.
This can be helpful with some "poor" ftp servers which don't
diff --git a/git-curl-compat.h b/git-curl-compat.h
index 703756ba85..aa8eed7ed2 100644
--- a/git-curl-compat.h
+++ b/git-curl-compat.h
@@ -45,4 +45,11 @@
#define GIT_CURL_HAVE_CURLOPT_PROTOCOLS_STR 1
#endif
+/**
+ * CURLOPT_TCP_KEEPCNT was added in 8.9.0, released in July, 2024.
+ */
+#if LIBCURL_VERSION_NUM >= 0x080900
+#define GIT_CURL_HAVE_CURLOPT_TCP_KEEPCNT
+#endif
+
#endif
diff --git a/http.c b/http.c
index 0c9a872809..d21e3a3bad 100644
--- a/http.c
+++ b/http.c
@@ -104,6 +104,10 @@ static struct {
};
#endif
+static long curl_tcp_keepidle = -1;
+static long curl_tcp_keepintvl = -1;
+static long curl_tcp_keepcnt = -1;
+
enum proactive_auth {
PROACTIVE_AUTH_NONE = 0,
PROACTIVE_AUTH_IF_CREDENTIALS,
@@ -438,11 +442,11 @@ static int http_options(const char *var, const char *value,
return 0;
}
if (!strcmp("http.lowspeedlimit", var)) {
- curl_low_speed_limit = (long)git_config_int(var, value, ctx->kvi);
+ curl_low_speed_limit = git_config_int(var, value, ctx->kvi);
return 0;
}
if (!strcmp("http.lowspeedtime", var)) {
- curl_low_speed_time = (long)git_config_int(var, value, ctx->kvi);
+ curl_low_speed_time = git_config_int(var, value, ctx->kvi);
return 0;
}
@@ -557,6 +561,19 @@ static int http_options(const char *var, const char *value,
return 0;
}
+ if (!strcmp("http.keepaliveidle", var)) {
+ curl_tcp_keepidle = git_config_int(var, value, ctx->kvi);
+ return 0;
+ }
+ if (!strcmp("http.keepaliveinterval", var)) {
+ curl_tcp_keepintvl = git_config_int(var, value, ctx->kvi);
+ return 0;
+ }
+ if (!strcmp("http.keepalivecount", var)) {
+ curl_tcp_keepcnt = git_config_int(var, value, ctx->kvi);
+ return 0;
+ }
+
/* Fall back on the default ones */
return git_default_config(var, value, ctx, data);
}
@@ -704,11 +721,6 @@ static int has_proxy_cert_password(void)
return 1;
}
-static void set_curl_keepalive(CURL *c)
-{
- curl_easy_setopt(c, CURLOPT_TCP_KEEPALIVE, 1);
-}
-
/* Return 1 if redactions have been made, 0 otherwise. */
static int redact_sensitive_header(struct strbuf *header, size_t offset)
{
@@ -1242,7 +1254,18 @@ static CURL *get_curl_handle(void)
}
init_curl_proxy_auth(result);
- set_curl_keepalive(result);
+ curl_easy_setopt(result, CURLOPT_TCP_KEEPALIVE, 1);
+
+ if (curl_tcp_keepidle > -1)
+ curl_easy_setopt(result, CURLOPT_TCP_KEEPIDLE,
+ curl_tcp_keepidle);
+ if (curl_tcp_keepintvl > -1)
+ curl_easy_setopt(result, CURLOPT_TCP_KEEPINTVL,
+ curl_tcp_keepintvl);
+#ifdef GIT_CURL_HAVE_CURLOPT_TCP_KEEPCNT
+ if (curl_tcp_keepcnt > -1)
+ curl_easy_setopt(result, CURLOPT_TCP_KEEPCNT, curl_tcp_keepcnt);
+#endif
return result;
}
@@ -1256,10 +1279,30 @@ static void set_from_env(char **var, const char *envname)
}
}
+static void set_long_from_env(long *var, const char *envname)
+{
+ const char *val = getenv(envname);
+ if (val) {
+ long tmp;
+ char *endp;
+ int saved_errno = errno;
+
+ errno = 0;
+ tmp = strtol(val, &endp, 10);
+
+ if (errno)
+ warning_errno(_("failed to parse %s"), envname);
+ else if (*endp || endp == val)
+ warning(_("failed to parse %s"), envname);
+ else
+ *var = tmp;
+
+ errno = saved_errno;
+ }
+}
+
void http_init(struct remote *remote, const char *url, int proactive_auth)
{
- char *low_speed_limit;
- char *low_speed_time;
char *normalized_url;
struct urlmatch_config config = URLMATCH_CONFIG_INIT;
@@ -1338,12 +1381,8 @@ void http_init(struct remote *remote, const char *url, int proactive_auth)
set_from_env(&user_agent, "GIT_HTTP_USER_AGENT");
- low_speed_limit = getenv("GIT_HTTP_LOW_SPEED_LIMIT");
- if (low_speed_limit)
- curl_low_speed_limit = strtol(low_speed_limit, NULL, 10);
- low_speed_time = getenv("GIT_HTTP_LOW_SPEED_TIME");
- if (low_speed_time)
- curl_low_speed_time = strtol(low_speed_time, NULL, 10);
+ set_long_from_env(&curl_low_speed_limit, "GIT_HTTP_LOW_SPEED_LIMIT");
+ set_long_from_env(&curl_low_speed_time, "GIT_HTTP_LOW_SPEED_TIME");
if (curl_ssl_verify == -1)
curl_ssl_verify = 1;
@@ -1370,6 +1409,10 @@ void http_init(struct remote *remote, const char *url, int proactive_auth)
ssl_cert_password_required = 1;
}
+ set_long_from_env(&curl_tcp_keepidle, "GIT_TCP_KEEPIDLE");
+ set_long_from_env(&curl_tcp_keepintvl, "GIT_TCP_KEEPINTVL");
+ set_long_from_env(&curl_tcp_keepcnt, "GIT_TCP_KEEPCNT");
+
curl_default = get_curl_handle();
}