Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 646 lines (557 sloc) 14.696 kb
29508e1 Isolate shared HTTP request functionality
Nick Hengeveld authored
1 #include "http.h"
2
3 int data_received;
4 int active_requests = 0;
5
6 #ifdef USE_CURL_MULTI
cc3530e Mike Hommey Cleanup variables in http.[ch]
glandium authored
7 static int max_requests = -1;
8 static CURLM *curlm;
29508e1 Isolate shared HTTP request functionality
Nick Hengeveld authored
9 #endif
10 #ifndef NO_CURL_EASY_DUPHANDLE
cc3530e Mike Hommey Cleanup variables in http.[ch]
glandium authored
11 static CURL *curl_default;
29508e1 Isolate shared HTTP request functionality
Nick Hengeveld authored
12 #endif
13 char curl_errorstr[CURL_ERROR_SIZE];
14
cc3530e Mike Hommey Cleanup variables in http.[ch]
glandium authored
15 static int curl_ssl_verify = -1;
16 static char *ssl_cert = NULL;
29508e1 Isolate shared HTTP request functionality
Nick Hengeveld authored
17 #if LIBCURL_VERSION_NUM >= 0x070902
cc3530e Mike Hommey Cleanup variables in http.[ch]
glandium authored
18 static char *ssl_key = NULL;
29508e1 Isolate shared HTTP request functionality
Nick Hengeveld authored
19 #endif
20 #if LIBCURL_VERSION_NUM >= 0x070908
cc3530e Mike Hommey Cleanup variables in http.[ch]
glandium authored
21 static char *ssl_capath = NULL;
29508e1 Isolate shared HTTP request functionality
Nick Hengeveld authored
22 #endif
cc3530e Mike Hommey Cleanup variables in http.[ch]
glandium authored
23 static char *ssl_cainfo = NULL;
24 static long curl_low_speed_limit = -1;
25 static long curl_low_speed_time = -1;
26 static int curl_ftp_no_epsv = 0;
27 static char *curl_http_proxy = NULL;
29508e1 Isolate shared HTTP request functionality
Nick Hengeveld authored
28
cc3530e Mike Hommey Cleanup variables in http.[ch]
glandium authored
29 static struct curl_slist *pragma_header;
29508e1 Isolate shared HTTP request functionality
Nick Hengeveld authored
30
cc3530e Mike Hommey Cleanup variables in http.[ch]
glandium authored
31 static struct active_request_slot *active_queue_head = NULL;
29508e1 Isolate shared HTTP request functionality
Nick Hengeveld authored
32
33 size_t fread_buffer(void *ptr, size_t eltsize, size_t nmemb,
34 struct buffer *buffer)
35 {
36 size_t size = eltsize * nmemb;
028c297 Mike Hommey Use strbuf in http code
glandium authored
37 if (size > buffer->buf.len - buffer->posn)
38 size = buffer->buf.len - buffer->posn;
39 memcpy(ptr, buffer->buf.buf + buffer->posn, size);
29508e1 Isolate shared HTTP request functionality
Nick Hengeveld authored
40 buffer->posn += size;
028c297 Mike Hommey Use strbuf in http code
glandium authored
41
29508e1 Isolate shared HTTP request functionality
Nick Hengeveld authored
42 return size;
43 }
44
45 size_t fwrite_buffer(const void *ptr, size_t eltsize,
028c297 Mike Hommey Use strbuf in http code
glandium authored
46 size_t nmemb, struct strbuf *buffer)
29508e1 Isolate shared HTTP request functionality
Nick Hengeveld authored
47 {
48 size_t size = eltsize * nmemb;
028c297 Mike Hommey Use strbuf in http code
glandium authored
49 strbuf_add(buffer, ptr, size);
29508e1 Isolate shared HTTP request functionality
Nick Hengeveld authored
50 data_received++;
51 return size;
52 }
53
54 size_t fwrite_null(const void *ptr, size_t eltsize,
028c297 Mike Hommey Use strbuf in http code
glandium authored
55 size_t nmemb, struct strbuf *buffer)
29508e1 Isolate shared HTTP request functionality
Nick Hengeveld authored
56 {
57 data_received++;
58 return eltsize * nmemb;
59 }
60
61 static void finish_active_slot(struct active_request_slot *slot);
62
63 #ifdef USE_CURL_MULTI
64 static void process_curl_messages(void)
65 {
66 int num_messages;
67 struct active_request_slot *slot;
68 CURLMsg *curl_message = curl_multi_info_read(curlm, &num_messages);
69
70 while (curl_message != NULL) {
71 if (curl_message->msg == CURLMSG_DONE) {
72 int curl_result = curl_message->data.result;
73 slot = active_queue_head;
74 while (slot != NULL &&
75 slot->curl != curl_message->easy_handle)
76 slot = slot->next;
77 if (slot != NULL) {
78 curl_multi_remove_handle(curlm, slot->curl);
79 slot->curl_result = curl_result;
80 finish_active_slot(slot);
81 } else {
82 fprintf(stderr, "Received DONE message for unknown request!\n");
83 }
84 } else {
85 fprintf(stderr, "Unknown CURL message received: %d\n",
86 (int)curl_message->msg);
87 }
88 curl_message = curl_multi_info_read(curlm, &num_messages);
89 }
90 }
91 #endif
92
93 static int http_options(const char *var, const char *value)
94 {
95 if (!strcmp("http.sslverify", var)) {
96 if (curl_ssl_verify == -1) {
97 curl_ssl_verify = git_config_bool(var, value);
98 }
99 return 0;
100 }
101
102 if (!strcmp("http.sslcert", var)) {
103 if (ssl_cert == NULL) {
111dd25 Junio C Hamano http.c: guard config parser from value=NULL
gitster authored
104 if (!value)
105 return config_error_nonbool(var);
106 ssl_cert = xstrdup(value);
29508e1 Isolate shared HTTP request functionality
Nick Hengeveld authored
107 }
108 return 0;
109 }
110 #if LIBCURL_VERSION_NUM >= 0x070902
111 if (!strcmp("http.sslkey", var)) {
112 if (ssl_key == NULL) {
111dd25 Junio C Hamano http.c: guard config parser from value=NULL
gitster authored
113 if (!value)
114 return config_error_nonbool(var);
115 ssl_key = xstrdup(value);
29508e1 Isolate shared HTTP request functionality
Nick Hengeveld authored
116 }
117 return 0;
118 }
119 #endif
120 #if LIBCURL_VERSION_NUM >= 0x070908
121 if (!strcmp("http.sslcapath", var)) {
122 if (ssl_capath == NULL) {
111dd25 Junio C Hamano http.c: guard config parser from value=NULL
gitster authored
123 if (!value)
124 return config_error_nonbool(var);
125 ssl_capath = xstrdup(value);
29508e1 Isolate shared HTTP request functionality
Nick Hengeveld authored
126 }
127 return 0;
128 }
129 #endif
130 if (!strcmp("http.sslcainfo", var)) {
131 if (ssl_cainfo == NULL) {
111dd25 Junio C Hamano http.c: guard config parser from value=NULL
gitster authored
132 if (!value)
133 return config_error_nonbool(var);
134 ssl_cainfo = xstrdup(value);
29508e1 Isolate shared HTTP request functionality
Nick Hengeveld authored
135 }
136 return 0;
137 }
138
a6080a0 Junio C Hamano War on whitespace
gitster authored
139 #ifdef USE_CURL_MULTI
29508e1 Isolate shared HTTP request functionality
Nick Hengeveld authored
140 if (!strcmp("http.maxrequests", var)) {
141 if (max_requests == -1)
142 max_requests = git_config_int(var, value);
143 return 0;
144 }
145 #endif
146
147 if (!strcmp("http.lowspeedlimit", var)) {
148 if (curl_low_speed_limit == -1)
149 curl_low_speed_limit = (long)git_config_int(var, value);
150 return 0;
151 }
152 if (!strcmp("http.lowspeedtime", var)) {
153 if (curl_low_speed_time == -1)
154 curl_low_speed_time = (long)git_config_int(var, value);
155 return 0;
156 }
157
3ea099d http/ftp: optionally ask curl to not use EPSV command
Sasha Khapyorsky authored
158 if (!strcmp("http.noepsv", var)) {
159 curl_ftp_no_epsv = git_config_bool(var, value);
160 return 0;
161 }
9c5665a Allow HTTP proxy to be overridden in config
Sam Vilain authored
162 if (!strcmp("http.proxy", var)) {
163 if (curl_http_proxy == NULL) {
111dd25 Junio C Hamano http.c: guard config parser from value=NULL
gitster authored
164 if (!value)
165 return config_error_nonbool(var);
166 curl_http_proxy = xstrdup(value);
9c5665a Allow HTTP proxy to be overridden in config
Sam Vilain authored
167 }
168 return 0;
169 }
3ea099d http/ftp: optionally ask curl to not use EPSV command
Sasha Khapyorsky authored
170
29508e1 Isolate shared HTTP request functionality
Nick Hengeveld authored
171 /* Fall back on the default ones */
172 return git_default_config(var, value);
173 }
174
11979b9 http.c: reorder to avoid compilation failure.
Junio C Hamano authored
175 static CURL* get_curl_handle(void)
176 {
177 CURL* result = curl_easy_init();
178
179 curl_easy_setopt(result, CURLOPT_SSL_VERIFYPEER, curl_ssl_verify);
180 #if LIBCURL_VERSION_NUM >= 0x070907
181 curl_easy_setopt(result, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
182 #endif
183
184 if (ssl_cert != NULL)
185 curl_easy_setopt(result, CURLOPT_SSLCERT, ssl_cert);
186 #if LIBCURL_VERSION_NUM >= 0x070902
187 if (ssl_key != NULL)
188 curl_easy_setopt(result, CURLOPT_SSLKEY, ssl_key);
189 #endif
190 #if LIBCURL_VERSION_NUM >= 0x070908
191 if (ssl_capath != NULL)
192 curl_easy_setopt(result, CURLOPT_CAPATH, ssl_capath);
193 #endif
194 if (ssl_cainfo != NULL)
195 curl_easy_setopt(result, CURLOPT_CAINFO, ssl_cainfo);
196 curl_easy_setopt(result, CURLOPT_FAILONERROR, 1);
197
198 if (curl_low_speed_limit > 0 && curl_low_speed_time > 0) {
199 curl_easy_setopt(result, CURLOPT_LOW_SPEED_LIMIT,
200 curl_low_speed_limit);
201 curl_easy_setopt(result, CURLOPT_LOW_SPEED_TIME,
202 curl_low_speed_time);
203 }
204
205 curl_easy_setopt(result, CURLOPT_FOLLOWLOCATION, 1);
206
7982d74 http: Turn on verbose Curl messages if GIT_CURL_VERBOSE set in environme...
Mark Wooding authored
207 if (getenv("GIT_CURL_VERBOSE"))
208 curl_easy_setopt(result, CURLOPT_VERBOSE, 1);
209
20fc9bc Set HTTP user agent to git/GIT_VERSION
Nick Hengeveld authored
210 curl_easy_setopt(result, CURLOPT_USERAGENT, GIT_USER_AGENT);
211
3ea099d http/ftp: optionally ask curl to not use EPSV command
Sasha Khapyorsky authored
212 if (curl_ftp_no_epsv)
213 curl_easy_setopt(result, CURLOPT_FTP_USE_EPSV, 0);
214
9c5665a Allow HTTP proxy to be overridden in config
Sam Vilain authored
215 if (curl_http_proxy)
216 curl_easy_setopt(result, CURLOPT_PROXY, curl_http_proxy);
217
11979b9 http.c: reorder to avoid compilation failure.
Junio C Hamano authored
218 return result;
219 }
220
9fc6440 Mike Hommey Set proxy override with http_init()
glandium authored
221 void http_init(struct remote *remote)
29508e1 Isolate shared HTTP request functionality
Nick Hengeveld authored
222 {
223 char *low_speed_limit;
224 char *low_speed_time;
225
226 curl_global_init(CURL_GLOBAL_ALL);
227
9fc6440 Mike Hommey Set proxy override with http_init()
glandium authored
228 if (remote && remote->http_proxy)
229 curl_http_proxy = xstrdup(remote->http_proxy);
230
29508e1 Isolate shared HTTP request functionality
Nick Hengeveld authored
231 pragma_header = curl_slist_append(pragma_header, "Pragma: no-cache");
232
233 #ifdef USE_CURL_MULTI
234 {
235 char *http_max_requests = getenv("GIT_HTTP_MAX_REQUESTS");
236 if (http_max_requests != NULL)
237 max_requests = atoi(http_max_requests);
238 }
239
240 curlm = curl_multi_init();
241 if (curlm == NULL) {
242 fprintf(stderr, "Error creating curl multi handle.\n");
243 exit(1);
244 }
245 #endif
246
247 if (getenv("GIT_SSL_NO_VERIFY"))
248 curl_ssl_verify = 0;
249
250 ssl_cert = getenv("GIT_SSL_CERT");
251 #if LIBCURL_VERSION_NUM >= 0x070902
252 ssl_key = getenv("GIT_SSL_KEY");
253 #endif
254 #if LIBCURL_VERSION_NUM >= 0x070908
255 ssl_capath = getenv("GIT_SSL_CAPATH");
256 #endif
257 ssl_cainfo = getenv("GIT_SSL_CAINFO");
258
259 low_speed_limit = getenv("GIT_HTTP_LOW_SPEED_LIMIT");
260 if (low_speed_limit != NULL)
261 curl_low_speed_limit = strtol(low_speed_limit, NULL, 10);
262 low_speed_time = getenv("GIT_HTTP_LOW_SPEED_TIME");
263 if (low_speed_time != NULL)
264 curl_low_speed_time = strtol(low_speed_time, NULL, 10);
265
266 git_config(http_options);
267
268 if (curl_ssl_verify == -1)
269 curl_ssl_verify = 1;
270
271 #ifdef USE_CURL_MULTI
272 if (max_requests < 1)
273 max_requests = DEFAULT_MAX_REQUESTS;
274 #endif
275
3ea099d http/ftp: optionally ask curl to not use EPSV command
Sasha Khapyorsky authored
276 if (getenv("GIT_CURL_FTP_NO_EPSV"))
277 curl_ftp_no_epsv = 1;
278
29508e1 Isolate shared HTTP request functionality
Nick Hengeveld authored
279 #ifndef NO_CURL_EASY_DUPHANDLE
280 curl_default = get_curl_handle();
281 #endif
282 }
283
284 void http_cleanup(void)
285 {
286 struct active_request_slot *slot = active_queue_head;
287
288 while (slot != NULL) {
3278cd0 Shawn O. Pearce Properly cleanup in http_cleanup so builtin-fetch does not segfault
spearce authored
289 struct active_request_slot *next = slot->next;
f23d1f7 Mike Hommey Fix random crashes in http_cleanup()
glandium authored
290 if (slot->curl != NULL) {
29508e1 Isolate shared HTTP request functionality
Nick Hengeveld authored
291 #ifdef USE_CURL_MULTI
f23d1f7 Mike Hommey Fix random crashes in http_cleanup()
glandium authored
292 curl_multi_remove_handle(curlm, slot->curl);
29508e1 Isolate shared HTTP request functionality
Nick Hengeveld authored
293 #endif
294 curl_easy_cleanup(slot->curl);
f23d1f7 Mike Hommey Fix random crashes in http_cleanup()
glandium authored
295 }
3278cd0 Shawn O. Pearce Properly cleanup in http_cleanup so builtin-fetch does not segfault
spearce authored
296 free(slot);
297 slot = next;
29508e1 Isolate shared HTTP request functionality
Nick Hengeveld authored
298 }
3278cd0 Shawn O. Pearce Properly cleanup in http_cleanup so builtin-fetch does not segfault
spearce authored
299 active_queue_head = NULL;
29508e1 Isolate shared HTTP request functionality
Nick Hengeveld authored
300
301 #ifndef NO_CURL_EASY_DUPHANDLE
302 curl_easy_cleanup(curl_default);
303 #endif
304
305 #ifdef USE_CURL_MULTI
306 curl_multi_cleanup(curlm);
307 #endif
308 curl_global_cleanup();
b3ca4e4 HTTP cleanup
Nick Hengeveld authored
309
310 curl_slist_free_all(pragma_header);
3278cd0 Shawn O. Pearce Properly cleanup in http_cleanup so builtin-fetch does not segfault
spearce authored
311 pragma_header = NULL;
9fc6440 Mike Hommey Set proxy override with http_init()
glandium authored
312
313 if (curl_http_proxy) {
314 free(curl_http_proxy);
315 curl_http_proxy = NULL;
316 }
29508e1 Isolate shared HTTP request functionality
Nick Hengeveld authored
317 }
318
319 struct active_request_slot *get_active_slot(void)
320 {
321 struct active_request_slot *slot = active_queue_head;
322 struct active_request_slot *newslot;
323
324 #ifdef USE_CURL_MULTI
325 int num_transfers;
326
327 /* Wait for a slot to open up if the queue is full */
328 while (active_requests >= max_requests) {
329 curl_multi_perform(curlm, &num_transfers);
330 if (num_transfers < active_requests) {
331 process_curl_messages();
332 }
333 }
334 #endif
335
336 while (slot != NULL && slot->in_use) {
337 slot = slot->next;
338 }
339 if (slot == NULL) {
340 newslot = xmalloc(sizeof(*newslot));
341 newslot->curl = NULL;
342 newslot->in_use = 0;
343 newslot->next = NULL;
344
345 slot = active_queue_head;
346 if (slot == NULL) {
347 active_queue_head = newslot;
348 } else {
349 while (slot->next != NULL) {
350 slot = slot->next;
351 }
352 slot->next = newslot;
353 }
354 slot = newslot;
355 }
356
357 if (slot->curl == NULL) {
358 #ifdef NO_CURL_EASY_DUPHANDLE
359 slot->curl = get_curl_handle();
360 #else
361 slot->curl = curl_easy_duphandle(curl_default);
362 #endif
363 }
364
365 active_requests++;
366 slot->in_use = 1;
367 slot->local = NULL;
c8568e1 Fix HTTP request result processing after slot reuse
Nick Hengeveld authored
368 slot->results = NULL;
baa7b67 HTTP slot reuse fixes
Nick Hengeveld authored
369 slot->finished = NULL;
29508e1 Isolate shared HTTP request functionality
Nick Hengeveld authored
370 slot->callback_data = NULL;
371 slot->callback_func = NULL;
372 curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, pragma_header);
373 curl_easy_setopt(slot->curl, CURLOPT_ERRORBUFFER, curl_errorstr);
9094950 http: prevent segfault during curl handle reuse
Nick Hengeveld authored
374 curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, NULL);
375 curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, NULL);
376 curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, NULL);
377 curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 0);
378 curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
29508e1 Isolate shared HTTP request functionality
Nick Hengeveld authored
379
380 return slot;
381 }
382
383 int start_active_slot(struct active_request_slot *slot)
384 {
385 #ifdef USE_CURL_MULTI
386 CURLMcode curlm_result = curl_multi_add_handle(curlm, slot->curl);
45c1741 Refactor http.h USE_CURL_MULTI fill_active_slots().
Daniel Barkalow authored
387 int num_transfers;
29508e1 Isolate shared HTTP request functionality
Nick Hengeveld authored
388
389 if (curlm_result != CURLM_OK &&
390 curlm_result != CURLM_CALL_MULTI_PERFORM) {
391 active_requests--;
392 slot->in_use = 0;
393 return 0;
394 }
45c1741 Refactor http.h USE_CURL_MULTI fill_active_slots().
Daniel Barkalow authored
395
396 /*
397 * We know there must be something to do, since we just added
398 * something.
399 */
400 curl_multi_perform(curlm, &num_transfers);
29508e1 Isolate shared HTTP request functionality
Nick Hengeveld authored
401 #endif
402 return 1;
403 }
404
405 #ifdef USE_CURL_MULTI
fc57b6a Make function to refill http queue a callback
Daniel Barkalow authored
406 struct fill_chain {
407 void *data;
408 int (*fill)(void *);
409 struct fill_chain *next;
410 };
411
412 static struct fill_chain *fill_cfg = NULL;
413
414 void add_fill_function(void *data, int (*fill)(void *))
415 {
416 struct fill_chain *new = malloc(sizeof(*new));
417 struct fill_chain **linkp = &fill_cfg;
418 new->data = data;
419 new->fill = fill;
420 new->next = NULL;
421 while (*linkp)
422 linkp = &(*linkp)->next;
423 *linkp = new;
424 }
425
45c1741 Refactor http.h USE_CURL_MULTI fill_active_slots().
Daniel Barkalow authored
426 void fill_active_slots(void)
427 {
428 struct active_request_slot *slot = active_queue_head;
429
fc57b6a Make function to refill http queue a callback
Daniel Barkalow authored
430 while (active_requests < max_requests) {
431 struct fill_chain *fill;
432 for (fill = fill_cfg; fill; fill = fill->next)
433 if (fill->fill(fill->data))
434 break;
435
436 if (!fill)
45c1741 Refactor http.h USE_CURL_MULTI fill_active_slots().
Daniel Barkalow authored
437 break;
fc57b6a Make function to refill http queue a callback
Daniel Barkalow authored
438 }
45c1741 Refactor http.h USE_CURL_MULTI fill_active_slots().
Daniel Barkalow authored
439
440 while (slot != NULL) {
441 if (!slot->in_use && slot->curl != NULL) {
442 curl_easy_cleanup(slot->curl);
443 slot->curl = NULL;
444 }
445 slot = slot->next;
446 }
447 }
448
29508e1 Isolate shared HTTP request functionality
Nick Hengeveld authored
449 void step_active_slots(void)
450 {
451 int num_transfers;
452 CURLMcode curlm_result;
453
454 do {
455 curlm_result = curl_multi_perform(curlm, &num_transfers);
456 } while (curlm_result == CURLM_CALL_MULTI_PERFORM);
457 if (num_transfers < active_requests) {
458 process_curl_messages();
459 fill_active_slots();
460 }
461 }
462 #endif
463
464 void run_active_slot(struct active_request_slot *slot)
465 {
466 #ifdef USE_CURL_MULTI
467 long last_pos = 0;
468 long current_pos;
469 fd_set readfds;
470 fd_set writefds;
471 fd_set excfds;
472 int max_fd;
473 struct timeval select_timeout;
baa7b67 HTTP slot reuse fixes
Nick Hengeveld authored
474 int finished = 0;
29508e1 Isolate shared HTTP request functionality
Nick Hengeveld authored
475
baa7b67 HTTP slot reuse fixes
Nick Hengeveld authored
476 slot->finished = &finished;
477 while (!finished) {
29508e1 Isolate shared HTTP request functionality
Nick Hengeveld authored
478 data_received = 0;
479 step_active_slots();
480
481 if (!data_received && slot->local != NULL) {
482 current_pos = ftell(slot->local);
483 if (current_pos > last_pos)
484 data_received++;
485 last_pos = current_pos;
486 }
487
488 if (slot->in_use && !data_received) {
489 max_fd = 0;
490 FD_ZERO(&readfds);
491 FD_ZERO(&writefds);
492 FD_ZERO(&excfds);
493 select_timeout.tv_sec = 0;
494 select_timeout.tv_usec = 50000;
495 select(max_fd, &readfds, &writefds,
496 &excfds, &select_timeout);
497 }
498 }
499 #else
500 while (slot->in_use) {
501 slot->curl_result = curl_easy_perform(slot->curl);
502 finish_active_slot(slot);
503 }
504 #endif
505 }
506
53f3138 http-fetch: Abort requests for objects which arrived in packs
Mark Wooding authored
507 static void closedown_active_slot(struct active_request_slot *slot)
29508e1 Isolate shared HTTP request functionality
Nick Hengeveld authored
508 {
028c297 Mike Hommey Use strbuf in http code
glandium authored
509 active_requests--;
510 slot->in_use = 0;
53f3138 http-fetch: Abort requests for objects which arrived in packs
Mark Wooding authored
511 }
512
513 void release_active_slot(struct active_request_slot *slot)
514 {
515 closedown_active_slot(slot);
516 if (slot->curl) {
b3ca4e4 HTTP cleanup
Nick Hengeveld authored
517 #ifdef USE_CURL_MULTI
53f3138 http-fetch: Abort requests for objects which arrived in packs
Mark Wooding authored
518 curl_multi_remove_handle(curlm, slot->curl);
b3ca4e4 HTTP cleanup
Nick Hengeveld authored
519 #endif
53f3138 http-fetch: Abort requests for objects which arrived in packs
Mark Wooding authored
520 curl_easy_cleanup(slot->curl);
521 slot->curl = NULL;
522 }
b3ca4e4 HTTP cleanup
Nick Hengeveld authored
523 #ifdef USE_CURL_MULTI
53f3138 http-fetch: Abort requests for objects which arrived in packs
Mark Wooding authored
524 fill_active_slots();
b3ca4e4 HTTP cleanup
Nick Hengeveld authored
525 #endif
53f3138 http-fetch: Abort requests for objects which arrived in packs
Mark Wooding authored
526 }
527
528 static void finish_active_slot(struct active_request_slot *slot)
529 {
530 closedown_active_slot(slot);
028c297 Mike Hommey Use strbuf in http code
glandium authored
531 curl_easy_getinfo(slot->curl, CURLINFO_HTTP_CODE, &slot->http_code);
c8568e1 Fix HTTP request result processing after slot reuse
Nick Hengeveld authored
532
baa7b67 HTTP slot reuse fixes
Nick Hengeveld authored
533 if (slot->finished != NULL)
534 (*slot->finished) = 1;
535
c8568e1 Fix HTTP request result processing after slot reuse
Nick Hengeveld authored
536 /* Store slot results so they can be read after the slot is reused */
537 if (slot->results != NULL) {
538 slot->results->curl_result = slot->curl_result;
539 slot->results->http_code = slot->http_code;
540 }
541
028c297 Mike Hommey Use strbuf in http code
glandium authored
542 /* Run callback if appropriate */
543 if (slot->callback_func != NULL) {
544 slot->callback_func(slot->callback_data);
545 }
29508e1 Isolate shared HTTP request functionality
Nick Hengeveld authored
546 }
547
548 void finish_all_active_slots(void)
549 {
550 struct active_request_slot *slot = active_queue_head;
551
552 while (slot != NULL)
553 if (slot->in_use) {
554 run_active_slot(slot);
555 slot = active_queue_head;
556 } else {
557 slot = slot->next;
558 }
559 }
d7e9280 Mike Hommey Move fetch_ref from http-push.c and http-walker.c to http.c
glandium authored
560
561 static inline int needs_quote(int ch)
562 {
563 if (((ch >= 'A') && (ch <= 'Z'))
564 || ((ch >= 'a') && (ch <= 'z'))
565 || ((ch >= '0') && (ch <= '9'))
566 || (ch == '/')
567 || (ch == '-')
568 || (ch == '.'))
569 return 0;
570 return 1;
571 }
572
573 static inline int hex(int v)
574 {
575 if (v < 10) return '0' + v;
576 else return 'A' + v - 10;
577 }
578
579 static char *quote_ref_url(const char *base, const char *ref)
580 {
581 const char *cp;
582 char *dp, *qref;
583 int len, baselen, ch;
584
585 baselen = strlen(base);
586 len = baselen + 7; /* "/refs/" + NUL */
587 for (cp = ref; (ch = *cp) != 0; cp++, len++)
588 if (needs_quote(ch))
589 len += 2; /* extra two hex plus replacement % */
590 qref = xmalloc(len);
591 memcpy(qref, base, baselen);
c13b263 Make walker.fetch_ref() take a struct ref.
Daniel Barkalow authored
592 dp = qref + baselen;
593 *(dp++) = '/';
594 for (cp = ref; (ch = *cp) != 0; cp++) {
d7e9280 Mike Hommey Move fetch_ref from http-push.c and http-walker.c to http.c
glandium authored
595 if (needs_quote(ch)) {
596 *dp++ = '%';
597 *dp++ = hex((ch >> 4) & 0xF);
598 *dp++ = hex(ch & 0xF);
599 }
600 else
601 *dp++ = ch;
602 }
603 *dp = 0;
604
605 return qref;
606 }
607
c13b263 Make walker.fetch_ref() take a struct ref.
Daniel Barkalow authored
608 int http_fetch_ref(const char *base, struct ref *ref)
d7e9280 Mike Hommey Move fetch_ref from http-push.c and http-walker.c to http.c
glandium authored
609 {
610 char *url;
611 struct strbuf buffer = STRBUF_INIT;
612 struct active_request_slot *slot;
613 struct slot_results results;
614 int ret;
615
c13b263 Make walker.fetch_ref() take a struct ref.
Daniel Barkalow authored
616 url = quote_ref_url(base, ref->name);
d7e9280 Mike Hommey Move fetch_ref from http-push.c and http-walker.c to http.c
glandium authored
617 slot = get_active_slot();
618 slot->results = &results;
619 curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer);
620 curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
621 curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, NULL);
622 curl_easy_setopt(slot->curl, CURLOPT_URL, url);
623 if (start_active_slot(slot)) {
624 run_active_slot(slot);
625 if (results.curl_result == CURLE_OK) {
626 strbuf_rtrim(&buffer);
627 if (buffer.len == 40)
c13b263 Make walker.fetch_ref() take a struct ref.
Daniel Barkalow authored
628 ret = get_sha1_hex(buffer.buf, ref->old_sha1);
be885d9 Make ls-remote http://... list HEAD, like for git://...
Daniel Barkalow authored
629 else if (!prefixcmp(buffer.buf, "ref: ")) {
630 ref->symref = xstrdup(buffer.buf + 5);
631 ret = 0;
632 } else
d7e9280 Mike Hommey Move fetch_ref from http-push.c and http-walker.c to http.c
glandium authored
633 ret = 1;
634 } else {
635 ret = error("Couldn't get %s for %s\n%s",
c13b263 Make walker.fetch_ref() take a struct ref.
Daniel Barkalow authored
636 url, ref->name, curl_errorstr);
d7e9280 Mike Hommey Move fetch_ref from http-push.c and http-walker.c to http.c
glandium authored
637 }
638 } else {
639 ret = error("Unable to start request");
640 }
641
642 strbuf_release(&buffer);
643 free(url);
644 return ret;
645 }
Something went wrong with that request. Please try again.