X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=http.c;h=87ebf7b86548d229afbfd9263d2470296a7b2ac7;hb=5410a02ab9e6a1987147724f8ea65e6a077b3832;hp=9604e3326bbc902aed987d2816fdf25450203633;hpb=9086a18cb81f99fff943b36830396ac8c37c7e9f;p=git.git diff --git a/http.c b/http.c index 9604e3326..87ebf7b86 100644 --- a/http.c +++ b/http.c @@ -23,9 +23,9 @@ char *ssl_capath = NULL; 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; @@ -35,7 +35,7 @@ size_t fread_buffer(void *ptr, size_t eltsize, size_t nmemb, 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; } @@ -50,7 +50,7 @@ size_t fwrite_buffer(const void *ptr, size_t eltsize, 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; @@ -137,7 +137,7 @@ static int http_options(const char *var, const char *value) 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); @@ -156,6 +156,11 @@ static int http_options(const char *var, const char *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); } @@ -195,6 +200,11 @@ static CURL* get_curl_handle(void) 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; } @@ -206,7 +216,6 @@ void http_init(void) 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 { @@ -251,6 +260,9 @@ void http_init(void) 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 @@ -264,6 +276,7 @@ void http_cleanup(void) #endif while (slot != NULL) { + struct active_request_slot *next = slot->next; #ifdef USE_CURL_MULTI if (slot->in_use) { curl_easy_getinfo(slot->curl, @@ -275,8 +288,10 @@ void http_cleanup(void) #endif if (slot->curl != NULL) curl_easy_cleanup(slot->curl); - slot = slot->next; + free(slot); + slot = next; } + active_queue_head = NULL; #ifndef NO_CURL_EASY_DUPHANDLE curl_easy_cleanup(curl_default); @@ -286,7 +301,9 @@ void http_cleanup(void) curl_multi_cleanup(curlm); #endif curl_global_cleanup(); - + + curl_slist_free_all(pragma_header); + pragma_header = NULL; } struct active_request_slot *get_active_slot(void) @@ -342,9 +359,14 @@ struct active_request_slot *get_active_slot(void) 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; } @@ -353,6 +375,7 @@ int start_active_slot(struct active_request_slot *slot) { #ifdef USE_CURL_MULTI CURLMcode curlm_result = curl_multi_add_handle(curlm, slot->curl); + int num_transfers; if (curlm_result != CURLM_OK && curlm_result != CURLM_CALL_MULTI_PERFORM) { @@ -360,11 +383,60 @@ int start_active_slot(struct active_request_slot *slot) slot->in_use = 0; return 0; } + + /* + * We know there must be something to do, since we just added + * something. + */ + curl_multi_perform(curlm, &num_transfers); #endif return 1; } #ifdef USE_CURL_MULTI +struct fill_chain { + void *data; + int (*fill)(void *); + struct fill_chain *next; +}; + +static struct fill_chain *fill_cfg = NULL; + +void add_fill_function(void *data, int (*fill)(void *)) +{ + struct fill_chain *new = malloc(sizeof(*new)); + struct fill_chain **linkp = &fill_cfg; + new->data = data; + new->fill = fill; + new->next = NULL; + while (*linkp) + linkp = &(*linkp)->next; + *linkp = new; +} + +void fill_active_slots(void) +{ + struct active_request_slot *slot = active_queue_head; + + while (active_requests < max_requests) { + struct fill_chain *fill; + for (fill = fill_cfg; fill; fill = fill->next) + if (fill->fill(fill->data)) + break; + + if (!fill) + break; + } + + while (slot != NULL) { + if (!slot->in_use && slot->curl != NULL) { + curl_easy_cleanup(slot->curl); + slot->curl = NULL; + } + slot = slot->next; + } +} + void step_active_slots(void) { int num_transfers; @@ -433,11 +505,15 @@ 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)