diff options
Diffstat (limited to 'http.c')
| -rw-r--r-- | http.c | 181 |
1 files changed, 116 insertions, 65 deletions
@@ -3,6 +3,7 @@ #include "git-compat-util.h" #include "git-curl-compat.h" +#include "environment.h" #include "hex.h" #include "http.h" #include "config.h" @@ -19,7 +20,7 @@ #include "packfile.h" #include "string-list.h" #include "object-file.h" -#include "object-store-ll.h" +#include "odb.h" #include "tempfile.h" static struct trace_key trace_curl = TRACE_KEY_INIT(CURL); @@ -104,6 +105,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 +443,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 +562,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); } @@ -598,8 +616,7 @@ static void init_curl_http_auth(CURL *result) { if ((!http_auth.username || !*http_auth.username) && (!http_auth.credential || !*http_auth.credential)) { - int empty_auth = curl_empty_auth_enabled(); - if ((empty_auth != -1 && !always_auth_proactively()) || empty_auth == 1) { + if (!always_auth_proactively() && curl_empty_auth_enabled()) { curl_easy_setopt(result, CURLOPT_USERPWD, ":"); return; } else if (!always_auth_proactively()) { @@ -609,7 +626,7 @@ static void init_curl_http_auth(CURL *result) } } - credential_fill(&http_auth, 1); + credential_fill(the_repository, &http_auth, 1); if (http_auth.password) { if (always_auth_proactively()) { @@ -652,7 +669,7 @@ static void init_curl_proxy_auth(CURL *result) { if (proxy_auth.username) { if (!proxy_auth.password && !proxy_auth.credential) - credential_fill(&proxy_auth, 1); + credential_fill(the_repository, &proxy_auth, 1); set_proxyauth_name_password(result); } @@ -686,7 +703,7 @@ static int has_cert_password(void) cert_auth.host = xstrdup(""); cert_auth.username = xstrdup(""); cert_auth.path = xstrdup(ssl_cert); - credential_fill(&cert_auth, 0); + credential_fill(the_repository, &cert_auth, 0); } return 1; } @@ -700,16 +717,11 @@ static int has_proxy_cert_password(void) proxy_cert_auth.host = xstrdup(""); proxy_cert_auth.username = xstrdup(""); proxy_cert_auth.path = xstrdup(http_proxy_ssl_cert); - credential_fill(&proxy_cert_auth, 0); + credential_fill(the_repository, &proxy_cert_auth, 0); } 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) { @@ -1008,13 +1020,13 @@ static CURL *get_curl_handle(void) die("curl_easy_init failed"); if (!curl_ssl_verify) { - curl_easy_setopt(result, CURLOPT_SSL_VERIFYPEER, 0); - curl_easy_setopt(result, CURLOPT_SSL_VERIFYHOST, 0); + curl_easy_setopt(result, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(result, CURLOPT_SSL_VERIFYHOST, 0L); } else { /* Verify authenticity of the peer's certificate */ - curl_easy_setopt(result, CURLOPT_SSL_VERIFYPEER, 1); + curl_easy_setopt(result, CURLOPT_SSL_VERIFYPEER, 1L); /* The name in the cert must match whom we tried to connect */ - curl_easy_setopt(result, CURLOPT_SSL_VERIFYHOST, 2); + curl_easy_setopt(result, CURLOPT_SSL_VERIFYHOST, 2L); } if (curl_http_version) { @@ -1046,7 +1058,7 @@ static CURL *get_curl_handle(void) if (http_ssl_backend && !strcmp("schannel", http_ssl_backend) && !http_schannel_check_revoke) { - curl_easy_setopt(result, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE); + curl_easy_setopt(result, CURLOPT_SSL_OPTIONS, (long)CURLSSLOPT_NO_REVOKE); } if (http_proactive_auth != PROACTIVE_AUTH_NONE) @@ -1106,8 +1118,8 @@ static CURL *get_curl_handle(void) curl_low_speed_time); } - curl_easy_setopt(result, CURLOPT_MAXREDIRS, 20); - curl_easy_setopt(result, CURLOPT_POSTREDIR, CURL_REDIR_POST_ALL); + curl_easy_setopt(result, CURLOPT_MAXREDIRS, 20L); + curl_easy_setopt(result, CURLOPT_POSTREDIR, (long)CURL_REDIR_POST_ALL); #ifdef GIT_CURL_HAVE_CURLOPT_PROTOCOLS_STR { @@ -1140,7 +1152,7 @@ static CURL *get_curl_handle(void) user_agent ? user_agent : git_user_agent()); if (curl_ftp_no_epsv) - curl_easy_setopt(result, CURLOPT_FTP_USE_EPSV, 0); + curl_easy_setopt(result, CURLOPT_FTP_USE_EPSV, 0L); if (curl_ssl_try) curl_easy_setopt(result, CURLOPT_USE_SSL, CURLUSESSL_TRY); @@ -1182,18 +1194,18 @@ static CURL *get_curl_handle(void) if (starts_with(curl_http_proxy, "socks5h")) curl_easy_setopt(result, - CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5_HOSTNAME); + CURLOPT_PROXYTYPE, (long)CURLPROXY_SOCKS5_HOSTNAME); else if (starts_with(curl_http_proxy, "socks5")) curl_easy_setopt(result, - CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); + CURLOPT_PROXYTYPE, (long)CURLPROXY_SOCKS5); else if (starts_with(curl_http_proxy, "socks4a")) curl_easy_setopt(result, - CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4A); + CURLOPT_PROXYTYPE, (long)CURLPROXY_SOCKS4A); else if (starts_with(curl_http_proxy, "socks")) curl_easy_setopt(result, - CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4); + CURLOPT_PROXYTYPE, (long)CURLPROXY_SOCKS4); else if (starts_with(curl_http_proxy, "https")) { - curl_easy_setopt(result, CURLOPT_PROXYTYPE, CURLPROXY_HTTPS); + curl_easy_setopt(result, CURLOPT_PROXYTYPE, (long)CURLPROXY_HTTPS); if (http_proxy_ssl_cert) curl_easy_setopt(result, CURLOPT_PROXY_SSLCERT, http_proxy_ssl_cert); @@ -1243,7 +1255,18 @@ static CURL *get_curl_handle(void) } init_curl_proxy_auth(result); - set_curl_keepalive(result); + curl_easy_setopt(result, CURLOPT_TCP_KEEPALIVE, 1L); + + 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; } @@ -1257,10 +1280,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; @@ -1273,7 +1316,7 @@ void http_init(struct remote *remote, const char *url, int proactive_auth) http_is_verbose = 0; normalized_url = url_normalize(url, &config.url); - git_config(urlmatch_config_entry, &config); + repo_config(the_repository, urlmatch_config_entry, &config); free(normalized_url); string_list_clear(&config.vars, 1); @@ -1305,6 +1348,14 @@ void http_init(struct remote *remote, const char *url, int proactive_auth) if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) die("curl_global_init failed"); +#ifdef GIT_CURL_HAVE_GLOBAL_TRACE + { + const char *comp = getenv("GIT_TRACE_CURL_COMPONENTS"); + if (comp) + curl_global_trace(comp); + } +#endif + if (proactive_auth && http_proactive_auth == PROACTIVE_AUTH_NONE) http_proactive_auth = PROACTIVE_AUTH_IF_CREDENTIALS; @@ -1339,12 +1390,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; @@ -1371,6 +1418,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(); } @@ -1498,9 +1549,9 @@ struct active_request_slot *get_active_slot(void) curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, NULL); curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDS, NULL); curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, -1L); - curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 0); - curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1); - curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 1); + curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 0L); + curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1L); + curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 1L); curl_easy_setopt(slot->curl, CURLOPT_RANGE, NULL); /* @@ -1509,9 +1560,9 @@ struct active_request_slot *get_active_slot(void) * HTTP_FOLLOW_* cases themselves. */ if (http_follow_config == HTTP_FOLLOW_ALWAYS) - curl_easy_setopt(slot->curl, CURLOPT_FOLLOWLOCATION, 1); + curl_easy_setopt(slot->curl, CURLOPT_FOLLOWLOCATION, 1L); else - curl_easy_setopt(slot->curl, CURLOPT_FOLLOWLOCATION, 0); + curl_easy_setopt(slot->curl, CURLOPT_FOLLOWLOCATION, 0L); curl_easy_setopt(slot->curl, CURLOPT_IPRESOLVE, git_curl_ipresolve); curl_easy_setopt(slot->curl, CURLOPT_HTTPAUTH, http_auth_methods); @@ -1784,9 +1835,9 @@ static int handle_curl_result(struct slot_results *results) curl_errorstr, sizeof(curl_errorstr)); if (results->curl_result == CURLE_OK) { - credential_approve(&http_auth); - credential_approve(&proxy_auth); - credential_approve(&cert_auth); + credential_approve(the_repository, &http_auth); + credential_approve(the_repository, &proxy_auth); + credential_approve(the_repository, &cert_auth); return HTTP_OK; } else if (results->curl_result == CURLE_SSL_CERTPROBLEM) { /* @@ -1795,7 +1846,7 @@ static int handle_curl_result(struct slot_results *results) * with the certificate. So we reject the credential to * avoid caching or saving a bad password. */ - credential_reject(&cert_auth); + credential_reject(the_repository, &cert_auth); return HTTP_NOAUTH; } else if (results->curl_result == CURLE_SSL_PINNEDPUBKEYNOTMATCH) { return HTTP_NOMATCHPUBLICKEY; @@ -1808,7 +1859,7 @@ static int handle_curl_result(struct slot_results *results) credential_clear_secrets(&http_auth); return HTTP_REAUTH; } - credential_reject(&http_auth); + credential_reject(the_repository, &http_auth); if (always_auth_proactively()) http_proactive_auth = PROACTIVE_AUTH_NONE; return HTTP_NOAUTH; @@ -1822,7 +1873,7 @@ static int handle_curl_result(struct slot_results *results) } } else { if (results->http_connectcode == 407) - credential_reject(&proxy_auth); + credential_reject(the_repository, &proxy_auth); if (!curl_errorstr[0]) strlcpy(curl_errorstr, curl_easy_strerror(results->curl_result), @@ -2078,12 +2129,12 @@ static int http_request(const char *url, int ret; slot = get_active_slot(); - curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1); + curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1L); if (!result) { - curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 1); + curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 1L); } else { - curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0); + curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0L); curl_easy_setopt(slot->curl, CURLOPT_WRITEDATA, result); if (target == HTTP_REQUEST_FILE) { @@ -2109,7 +2160,7 @@ static int http_request(const char *url, strbuf_addstr(&buf, " no-cache"); if (options && options->initial_request && http_follow_config == HTTP_FOLLOW_INITIAL) - curl_easy_setopt(slot->curl, CURLOPT_FOLLOWLOCATION, 1); + curl_easy_setopt(slot->curl, CURLOPT_FOLLOWLOCATION, 1L); headers = curl_slist_append(headers, buf.buf); @@ -2128,7 +2179,7 @@ static int http_request(const char *url, curl_easy_setopt(slot->curl, CURLOPT_URL, url); curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(slot->curl, CURLOPT_ENCODING, ""); - curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 0); + curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 0L); ret = run_one_slot(slot, &results); @@ -2210,7 +2261,7 @@ static int http_request_reauth(const char *url, int ret; if (always_auth_proactively()) - credential_fill(&http_auth, 1); + credential_fill(the_repository, &http_auth, 1); ret = http_request(url, result, target, options); @@ -2251,7 +2302,7 @@ static int http_request_reauth(const char *url, BUG("Unknown http_request target"); } - credential_fill(&http_auth, 1); + credential_fill(the_repository, &http_auth, 1); ret = http_request(url, result, target, options); } @@ -2289,7 +2340,7 @@ int http_get_file(const char *url, const char *filename, ret = http_request_reauth(url, result, HTTP_REQUEST_FILE, options); fclose(result); - if (ret == HTTP_OK && finalize_object_file(tmpfile.buf, filename)) + if (ret == HTTP_OK && finalize_object_file(the_repository, tmpfile.buf, filename)) ret = HTTP_ERROR; cleanup: strbuf_release(&tmpfile); @@ -2373,7 +2424,7 @@ static int fetch_and_setup_pack_index(struct packed_git **packs_head, * If we already have the pack locally, no need to fetch its index or * even add it to list; we already have all of its objects. */ - for (p = get_all_packs(the_repository); p; p = p->next) { + repo_for_each_pack(the_repository, p) { if (hasheq(p->hash, sha1, the_repository->hash_algo)) return 0; } @@ -2498,7 +2549,7 @@ void http_install_packfile(struct packed_git *p, lst = &((*lst)->next); *lst = (*lst)->next; - install_packed_git(the_repository, p); + packfile_store_add_pack(the_repository->objects->packfiles, p); } struct http_pack_request *new_http_pack_request( @@ -2597,8 +2648,8 @@ static size_t fwrite_sha1_file(char *ptr, size_t eltsize, size_t nmemb, freq->stream.next_out = expn; freq->stream.avail_out = sizeof(expn); freq->zret = git_inflate(&freq->stream, Z_SYNC_FLUSH); - the_hash_algo->update_fn(&freq->c, expn, - sizeof(expn) - freq->stream.avail_out); + git_hash_update(&freq->c, expn, + sizeof(expn) - freq->stream.avail_out); } while (freq->stream.avail_in && freq->zret == Z_OK); return nmemb; } @@ -2620,7 +2671,7 @@ struct http_object_request *new_http_object_request(const char *base_url, oidcpy(&freq->oid, oid); freq->localfile = -1; - loose_object_path(the_repository, &filename, oid); + odb_loose_path(the_repository->objects->sources, &filename, oid); strbuf_addf(&freq->tmpfile, "%s.temp", filename.buf); strbuf_addf(&prevfile, "%s.prev", filename.buf); @@ -2708,7 +2759,7 @@ struct http_object_request *new_http_object_request(const char *base_url, freq->headers = object_request_headers(); curl_easy_setopt(freq->slot->curl, CURLOPT_WRITEDATA, freq); - curl_easy_setopt(freq->slot->curl, CURLOPT_FAILONERROR, 0); + curl_easy_setopt(freq->slot->curl, CURLOPT_FAILONERROR, 0L); curl_easy_setopt(freq->slot->curl, CURLOPT_WRITEFUNCTION, fwrite_sha1_file); curl_easy_setopt(freq->slot->curl, CURLOPT_ERRORBUFFER, freq->errorstr); curl_easy_setopt(freq->slot->curl, CURLOPT_URL, freq->url); @@ -2763,7 +2814,7 @@ int finish_http_object_request(struct http_object_request *freq) return -1; } - the_hash_algo->final_oid_fn(&freq->real_oid, &freq->c); + git_hash_final_oid(&freq->real_oid, &freq->c); if (freq->zret != Z_STREAM_END) { unlink_or_warn(freq->tmpfile.buf); return -1; @@ -2772,8 +2823,8 @@ int finish_http_object_request(struct http_object_request *freq) unlink_or_warn(freq->tmpfile.buf); return -1; } - loose_object_path(the_repository, &filename, &freq->oid); - freq->rename = finalize_object_file(freq->tmpfile.buf, filename.buf); + odb_loose_path(the_repository->objects->sources, &filename, &freq->oid); + freq->rename = finalize_object_file(the_repository, freq->tmpfile.buf, filename.buf); strbuf_release(&filename); return freq->rename; |
