char *ssl_cainfo = NULL;
long curl_low_speed_limit = -1;
long curl_low_speed_time = -1;
+int curl_ftp_no_epsv = 0;
struct curl_slist *pragma_header;
-struct curl_slist *no_range_header;
struct active_request_slot *active_queue_head = NULL;
size_t size = eltsize * nmemb;
if (size > buffer->size - buffer->posn)
size = buffer->size - buffer->posn;
- memcpy(ptr, buffer->buffer + buffer->posn, size);
+ memcpy(ptr, (char *) buffer->buffer + buffer->posn, size);
buffer->posn += size;
return size;
}
buffer->size = buffer->posn + size;
buffer->buffer = xrealloc(buffer->buffer, buffer->size);
}
- memcpy(buffer->buffer + buffer->posn, ptr, size);
+ memcpy((char *) buffer->buffer + buffer->posn, ptr, size);
buffer->posn += size;
data_received++;
return size;
return 0;
}
-#ifdef USE_CURL_MULTI
+#ifdef USE_CURL_MULTI
if (!strcmp("http.maxrequests", var)) {
if (max_requests == -1)
max_requests = git_config_int(var, value);
return 0;
}
+ if (!strcmp("http.noepsv", var)) {
+ curl_ftp_no_epsv = git_config_bool(var, value);
+ return 0;
+ }
+
/* Fall back on the default ones */
return git_default_config(var, value);
}
+static CURL* get_curl_handle(void)
+{
+ CURL* result = curl_easy_init();
+
+ curl_easy_setopt(result, CURLOPT_SSL_VERIFYPEER, curl_ssl_verify);
+#if LIBCURL_VERSION_NUM >= 0x070907
+ curl_easy_setopt(result, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
+#endif
+
+ if (ssl_cert != NULL)
+ curl_easy_setopt(result, CURLOPT_SSLCERT, ssl_cert);
+#if LIBCURL_VERSION_NUM >= 0x070902
+ if (ssl_key != NULL)
+ curl_easy_setopt(result, CURLOPT_SSLKEY, ssl_key);
+#endif
+#if LIBCURL_VERSION_NUM >= 0x070908
+ if (ssl_capath != NULL)
+ curl_easy_setopt(result, CURLOPT_CAPATH, ssl_capath);
+#endif
+ if (ssl_cainfo != NULL)
+ curl_easy_setopt(result, CURLOPT_CAINFO, ssl_cainfo);
+ curl_easy_setopt(result, CURLOPT_FAILONERROR, 1);
+
+ if (curl_low_speed_limit > 0 && curl_low_speed_time > 0) {
+ curl_easy_setopt(result, CURLOPT_LOW_SPEED_LIMIT,
+ curl_low_speed_limit);
+ curl_easy_setopt(result, CURLOPT_LOW_SPEED_TIME,
+ curl_low_speed_time);
+ }
+
+ curl_easy_setopt(result, CURLOPT_FOLLOWLOCATION, 1);
+
+ if (getenv("GIT_CURL_VERBOSE"))
+ curl_easy_setopt(result, CURLOPT_VERBOSE, 1);
+
+ curl_easy_setopt(result, CURLOPT_USERAGENT, GIT_USER_AGENT);
+
+ if (curl_ftp_no_epsv)
+ curl_easy_setopt(result, CURLOPT_FTP_USE_EPSV, 0);
+
+ return result;
+}
+
void http_init(void)
{
char *low_speed_limit;
curl_global_init(CURL_GLOBAL_ALL);
pragma_header = curl_slist_append(pragma_header, "Pragma: no-cache");
- no_range_header = curl_slist_append(no_range_header, "Range:");
#ifdef USE_CURL_MULTI
{
max_requests = DEFAULT_MAX_REQUESTS;
#endif
+ if (getenv("GIT_CURL_FTP_NO_EPSV"))
+ curl_ftp_no_epsv = 1;
+
#ifndef NO_CURL_EASY_DUPHANDLE
curl_default = get_curl_handle();
#endif
struct active_request_slot *slot = active_queue_head;
#ifdef USE_CURL_MULTI
char *wait_url;
- CURLMcode curlm_result;
#endif
while (slot != NULL) {
curl_multi_cleanup(curlm);
#endif
curl_global_cleanup();
-
-}
-
-static CURL* get_curl_handle(void)
-{
- CURL* result = curl_easy_init();
-
- curl_easy_setopt(result, CURLOPT_SSL_VERIFYPEER, curl_ssl_verify);
-#if LIBCURL_VERSION_NUM >= 0x070907
- curl_easy_setopt(result, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
-#endif
-
- if (ssl_cert != NULL)
- curl_easy_setopt(result, CURLOPT_SSLCERT, ssl_cert);
-#if LIBCURL_VERSION_NUM >= 0x070902
- if (ssl_key != NULL)
- curl_easy_setopt(result, CURLOPT_SSLKEY, ssl_key);
-#endif
-#if LIBCURL_VERSION_NUM >= 0x070908
- if (ssl_capath != NULL)
- curl_easy_setopt(result, CURLOPT_CAPATH, ssl_capath);
-#endif
- if (ssl_cainfo != NULL)
- curl_easy_setopt(result, CURLOPT_CAINFO, ssl_cainfo);
- curl_easy_setopt(result, CURLOPT_FAILONERROR, 1);
-
- if (curl_low_speed_limit > 0 && curl_low_speed_time > 0) {
- curl_easy_setopt(result, CURLOPT_LOW_SPEED_LIMIT,
- curl_low_speed_limit);
- curl_easy_setopt(result, CURLOPT_LOW_SPEED_TIME,
- curl_low_speed_time);
- }
- curl_easy_setopt(result, CURLOPT_FOLLOWLOCATION, 1);
-
- return result;
+ curl_slist_free_all(pragma_header);
+ pragma_header = NULL;
}
struct active_request_slot *get_active_slot(void)
active_requests++;
slot->in_use = 1;
slot->local = NULL;
+ slot->results = NULL;
+ slot->finished = NULL;
slot->callback_data = NULL;
slot->callback_func = NULL;
+ curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, NULL);
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, pragma_header);
- curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, no_range_header);
curl_easy_setopt(slot->curl, CURLOPT_ERRORBUFFER, curl_errorstr);
+ curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, NULL);
+ curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, NULL);
+ curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, NULL);
+ curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 0);
+ curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
return slot;
}
fd_set excfds;
int max_fd;
struct timeval select_timeout;
+ int finished = 0;
- while (slot->in_use) {
+ slot->finished = &finished;
+ while (!finished) {
data_received = 0;
step_active_slots();
#endif
}
-static void finish_active_slot(struct active_request_slot *slot)
+static void closedown_active_slot(struct active_request_slot *slot)
{
active_requests--;
slot->in_use = 0;
+}
+
+void release_active_slot(struct active_request_slot *slot)
+{
+ closedown_active_slot(slot);
+ if (slot->curl) {
+#ifdef USE_CURL_MULTI
+ curl_multi_remove_handle(curlm, slot->curl);
+#endif
+ curl_easy_cleanup(slot->curl);
+ slot->curl = NULL;
+ }
+#ifdef USE_CURL_MULTI
+ fill_active_slots();
+#endif
+}
+
+static void finish_active_slot(struct active_request_slot *slot)
+{
+ closedown_active_slot(slot);
curl_easy_getinfo(slot->curl, CURLINFO_HTTP_CODE, &slot->http_code);
-
+
+ if (slot->finished != NULL)
+ (*slot->finished) = 1;
+
+ /* Store slot results so they can be read after the slot is reused */
+ if (slot->results != NULL) {
+ slot->results->curl_result = slot->curl_result;
+ slot->results->http_code = slot->http_code;
+ }
+
/* Run callback if appropriate */
if (slot->callback_func != NULL) {
slot->callback_func(slot->callback_data);