Skip to content
Navigation Menu
Toggle navigation
Sign in
In this repository
All GitHub Enterprise
↵
Jump to
↵
No suggested jump to results
In this repository
All GitHub Enterprise
↵
Jump to
↵
In this organization
All GitHub Enterprise
↵
Jump to
↵
In this repository
All GitHub Enterprise
↵
Jump to
↵
Sign in
Reseting focus
You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
Dismiss alert
{{ message }}
git-mirror
/
git
Public
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Issues
0
Pull requests
0
Actions
Projects
0
Security
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Security
Insights
Files
3ea099d
Documentation
arm
compat
contrib
gitweb
mozilla-sha1
ppc
t
templates
xdiff
.gitignore
COPYING
GIT-VERSION-GEN
INSTALL
Makefile
README
alloc.c
archive-tar.c
archive-zip.c
archive.h
base85.c
blame.c
blob.c
blob.h
builtin-add.c
builtin-apply.c
builtin-archive.c
builtin-cat-file.c
builtin-check-ref-format.c
builtin-checkout-index.c
builtin-commit-tree.c
builtin-count-objects.c
builtin-diff-files.c
builtin-diff-index.c
builtin-diff-stages.c
builtin-diff-tree.c
builtin-diff.c
builtin-fmt-merge-msg.c
builtin-grep.c
builtin-init-db.c
builtin-log.c
builtin-ls-files.c
builtin-ls-tree.c
builtin-mailinfo.c
builtin-mailsplit.c
builtin-mv.c
builtin-name-rev.c
builtin-pack-objects.c
builtin-prune-packed.c
builtin-prune.c
builtin-push.c
builtin-read-tree.c
builtin-repo-config.c
builtin-rev-list.c
builtin-rev-parse.c
builtin-rm.c
builtin-runstatus.c
builtin-show-branch.c
builtin-stripspace.c
builtin-symbolic-ref.c
builtin-tar-tree.c
builtin-unpack-objects.c
builtin-update-index.c
builtin-update-ref.c
builtin-upload-archive.c
builtin-verify-pack.c
builtin-write-tree.c
builtin.h
cache-tree.c
cache-tree.h
cache.h
check-racy.c
color.c
color.h
combine-diff.c
commit.c
commit.h
config.c
config.mak.in
configure.ac
connect.c
convert-objects.c
copy.c
csum-file.c
csum-file.h
ctype.c
daemon.c
date.c
delta.h
describe.c
diff-delta.c
diff-lib.c
diff.c
diff.h
diffcore-break.c
diffcore-delta.c
diffcore-order.c
diffcore-pickaxe.c
diffcore-rename.c
diffcore.h
dir.c
dir.h
dump-cache-tree.c
entry.c
environment.c
exec_cmd.c
exec_cmd.h
fetch-clone.c
fetch-pack.c
fetch.c
fetch.h
fsck-objects.c
generate-cmdlist.sh
git-am.sh
git-annotate.perl
git-applymbox.sh
git-applypatch.sh
git-archimport.perl
git-bisect.sh
git-branch.sh
git-checkout.sh
git-cherry.sh
git-clean.sh
git-clone.sh
git-commit.sh
git-compat-util.h
git-cvsexportcommit.perl
git-cvsimport.perl
git-cvsserver.perl
git-fetch.sh
git-instaweb.sh
git-lost-found.sh
git-ls-remote.sh
git-merge-octopus.sh
git-merge-one-file.sh
git-merge-ours.sh
git-merge-recursive-old.py
git-merge-resolve.sh
git-merge-stupid.sh
git-merge.sh
git-p4import.py
git-parse-remote.sh
git-pull.sh
git-quiltimport.sh
git-rebase.sh
git-relink.perl
git-repack.sh
git-request-pull.sh
git-rerere.perl
git-reset.sh
git-resolve.sh
git-revert.sh
git-send-email.perl
git-sh-setup.sh
git-shortlog.perl
git-svn.perl
git-svnimport.perl
git-tag.sh
git-verify-tag.sh
git.c
git.spec.in
gitMergeCommon.py
gitk
grep.c
grep.h
hash-object.c
help.c
http-fetch.c
http-push.c
http.c
http.h
ident.c
imap-send.c
index-pack.c
interpolate.c
interpolate.h
list-objects.c
list-objects.h
local-fetch.c
lockfile.c
log-tree.c
log-tree.h
merge-base.c
merge-file.c
merge-index.c
merge-recursive.c
merge-tree.c
mktag.c
mktree.c
object-refs.c
object.c
object.h
pack-check.c
pack-redundant.c
pack.h
pager.c
patch-delta.c
patch-id.c
path-list.c
path-list.h
path.c
peek-remote.c
pkt-line.c
pkt-line.h
quote.c
quote.h
read-cache.c
receive-pack.c
refs.c
refs.h
revision.c
revision.h
rsh.c
rsh.h
run-command.c
run-command.h
send-pack.c
server-info.c
setup.c
sha1_file.c
sha1_name.c
shell.c
show-index.c
sideband.c
sideband.h
ssh-fetch.c
ssh-pull.c
ssh-push.c
ssh-upload.c
strbuf.c
strbuf.h
tag.c
tag.h
tar.h
test-date.c
test-delta.c
test-sha1.c
test-sha1.sh
trace.c
tree-diff.c
tree-walk.c
tree-walk.h
tree.c
tree.h
unpack-file.c
unpack-trees.c
unpack-trees.h
update-server-info.c
upload-pack.c
usage.c
var.c
write_or_die.c
wt-status.c
wt-status.h
xdiff-interface.c
xdiff-interface.h
Breadcrumbs
git
/
http.c
Blame
Blame
Latest commit
History
History
496 lines (428 loc) · 11.3 KB
Breadcrumbs
git
/
http.c
Top
File metadata and controls
Code
Blame
496 lines (428 loc) · 11.3 KB
Raw
#include "http.h" int data_received; int active_requests = 0; #ifdef USE_CURL_MULTI int max_requests = -1; CURLM *curlm; #endif #ifndef NO_CURL_EASY_DUPHANDLE CURL *curl_default; #endif char curl_errorstr[CURL_ERROR_SIZE]; int curl_ssl_verify = -1; char *ssl_cert = NULL; #if LIBCURL_VERSION_NUM >= 0x070902 char *ssl_key = NULL; #endif #if LIBCURL_VERSION_NUM >= 0x070908 char *ssl_capath = NULL; #endif 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 active_request_slot *active_queue_head = NULL; size_t fread_buffer(void *ptr, size_t eltsize, size_t nmemb, struct buffer *buffer) { size_t size = eltsize * nmemb; if (size > buffer->size - buffer->posn) size = buffer->size - buffer->posn; memcpy(ptr, (char *) buffer->buffer + buffer->posn, size); buffer->posn += size; return size; } size_t fwrite_buffer(const void *ptr, size_t eltsize, size_t nmemb, struct buffer *buffer) { size_t size = eltsize * nmemb; if (size > buffer->size - buffer->posn) { buffer->size = buffer->size * 3 / 2; if (buffer->size < buffer->posn + size) buffer->size = buffer->posn + size; buffer->buffer = xrealloc(buffer->buffer, buffer->size); } memcpy((char *) buffer->buffer + buffer->posn, ptr, size); buffer->posn += size; data_received++; return size; } size_t fwrite_null(const void *ptr, size_t eltsize, size_t nmemb, struct buffer *buffer) { data_received++; return eltsize * nmemb; } static void finish_active_slot(struct active_request_slot *slot); #ifdef USE_CURL_MULTI static void process_curl_messages(void) { int num_messages; struct active_request_slot *slot; CURLMsg *curl_message = curl_multi_info_read(curlm, &num_messages); while (curl_message != NULL) { if (curl_message->msg == CURLMSG_DONE) { int curl_result = curl_message->data.result; slot = active_queue_head; while (slot != NULL && slot->curl != curl_message->easy_handle) slot = slot->next; if (slot != NULL) { curl_multi_remove_handle(curlm, slot->curl); slot->curl_result = curl_result; finish_active_slot(slot); } else { fprintf(stderr, "Received DONE message for unknown request!\n"); } } else { fprintf(stderr, "Unknown CURL message received: %d\n", (int)curl_message->msg); } curl_message = curl_multi_info_read(curlm, &num_messages); } } #endif static int http_options(const char *var, const char *value) { if (!strcmp("http.sslverify", var)) { if (curl_ssl_verify == -1) { curl_ssl_verify = git_config_bool(var, value); } return 0; } if (!strcmp("http.sslcert", var)) { if (ssl_cert == NULL) { ssl_cert = xmalloc(strlen(value)+1); strcpy(ssl_cert, value); } return 0; } #if LIBCURL_VERSION_NUM >= 0x070902 if (!strcmp("http.sslkey", var)) { if (ssl_key == NULL) { ssl_key = xmalloc(strlen(value)+1); strcpy(ssl_key, value); } return 0; } #endif #if LIBCURL_VERSION_NUM >= 0x070908 if (!strcmp("http.sslcapath", var)) { if (ssl_capath == NULL) { ssl_capath = xmalloc(strlen(value)+1); strcpy(ssl_capath, value); } return 0; } #endif if (!strcmp("http.sslcainfo", var)) { if (ssl_cainfo == NULL) { ssl_cainfo = xmalloc(strlen(value)+1); strcpy(ssl_cainfo, value); } return 0; } #ifdef USE_CURL_MULTI if (!strcmp("http.maxrequests", var)) { if (max_requests == -1) max_requests = git_config_int(var, value); return 0; } #endif if (!strcmp("http.lowspeedlimit", var)) { if (curl_low_speed_limit == -1) curl_low_speed_limit = (long)git_config_int(var, value); return 0; } if (!strcmp("http.lowspeedtime", var)) { if (curl_low_speed_time == -1) curl_low_speed_time = (long)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; char *low_speed_time; curl_global_init(CURL_GLOBAL_ALL); pragma_header = curl_slist_append(pragma_header, "Pragma: no-cache"); #ifdef USE_CURL_MULTI { char *http_max_requests = getenv("GIT_HTTP_MAX_REQUESTS"); if (http_max_requests != NULL) max_requests = atoi(http_max_requests); } curlm = curl_multi_init(); if (curlm == NULL) { fprintf(stderr, "Error creating curl multi handle.\n"); exit(1); } #endif if (getenv("GIT_SSL_NO_VERIFY")) curl_ssl_verify = 0; ssl_cert = getenv("GIT_SSL_CERT"); #if LIBCURL_VERSION_NUM >= 0x070902 ssl_key = getenv("GIT_SSL_KEY"); #endif #if LIBCURL_VERSION_NUM >= 0x070908 ssl_capath = getenv("GIT_SSL_CAPATH"); #endif ssl_cainfo = getenv("GIT_SSL_CAINFO"); low_speed_limit = getenv("GIT_HTTP_LOW_SPEED_LIMIT"); if (low_speed_limit != NULL) curl_low_speed_limit = strtol(low_speed_limit, NULL, 10); low_speed_time = getenv("GIT_HTTP_LOW_SPEED_TIME"); if (low_speed_time != NULL) curl_low_speed_time = strtol(low_speed_time, NULL, 10); git_config(http_options); if (curl_ssl_verify == -1) curl_ssl_verify = 1; #ifdef USE_CURL_MULTI if (max_requests < 1) 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 } void http_cleanup(void) { struct active_request_slot *slot = active_queue_head; #ifdef USE_CURL_MULTI char *wait_url; #endif while (slot != NULL) { #ifdef USE_CURL_MULTI if (slot->in_use) { curl_easy_getinfo(slot->curl, CURLINFO_EFFECTIVE_URL, &wait_url); fprintf(stderr, "Waiting for %s\n", wait_url); run_active_slot(slot); } #endif if (slot->curl != NULL) curl_easy_cleanup(slot->curl); slot = slot->next; } #ifndef NO_CURL_EASY_DUPHANDLE curl_easy_cleanup(curl_default); #endif #ifdef USE_CURL_MULTI curl_multi_cleanup(curlm); #endif curl_global_cleanup(); curl_slist_free_all(pragma_header); } struct active_request_slot *get_active_slot(void) { struct active_request_slot *slot = active_queue_head; struct active_request_slot *newslot; #ifdef USE_CURL_MULTI int num_transfers; /* Wait for a slot to open up if the queue is full */ while (active_requests >= max_requests) { curl_multi_perform(curlm, &num_transfers); if (num_transfers < active_requests) { process_curl_messages(); } } #endif while (slot != NULL && slot->in_use) { slot = slot->next; } if (slot == NULL) { newslot = xmalloc(sizeof(*newslot)); newslot->curl = NULL; newslot->in_use = 0; newslot->next = NULL; slot = active_queue_head; if (slot == NULL) { active_queue_head = newslot; } else { while (slot->next != NULL) { slot = slot->next; } slot->next = newslot; } slot = newslot; } if (slot->curl == NULL) { #ifdef NO_CURL_EASY_DUPHANDLE slot->curl = get_curl_handle(); #else slot->curl = curl_easy_duphandle(curl_default); #endif } 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_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; } int start_active_slot(struct active_request_slot *slot) { #ifdef USE_CURL_MULTI CURLMcode curlm_result = curl_multi_add_handle(curlm, slot->curl); if (curlm_result != CURLM_OK && curlm_result != CURLM_CALL_MULTI_PERFORM) { active_requests--; slot->in_use = 0; return 0; } #endif return 1; } #ifdef USE_CURL_MULTI void step_active_slots(void) { int num_transfers; CURLMcode curlm_result; do { curlm_result = curl_multi_perform(curlm, &num_transfers); } while (curlm_result == CURLM_CALL_MULTI_PERFORM); if (num_transfers < active_requests) { process_curl_messages(); fill_active_slots(); } } #endif void run_active_slot(struct active_request_slot *slot) { #ifdef USE_CURL_MULTI long last_pos = 0; long current_pos; fd_set readfds; fd_set writefds; fd_set excfds; int max_fd; struct timeval select_timeout; int finished = 0; slot->finished = &finished; while (!finished) { data_received = 0; step_active_slots(); if (!data_received && slot->local != NULL) { current_pos = ftell(slot->local); if (current_pos > last_pos) data_received++; last_pos = current_pos; } if (slot->in_use && !data_received) { max_fd = 0; FD_ZERO(&readfds); FD_ZERO(&writefds); FD_ZERO(&excfds); select_timeout.tv_sec = 0; select_timeout.tv_usec = 50000; select(max_fd, &readfds, &writefds, &excfds, &select_timeout); } } #else while (slot->in_use) { slot->curl_result = curl_easy_perform(slot->curl); finish_active_slot(slot); } #endif } 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); } } void finish_all_active_slots(void) { struct active_request_slot *slot = active_queue_head; while (slot != NULL) if (slot->in_use) { run_active_slot(slot); slot = active_queue_head; } else { slot = slot->next; } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
You can’t perform that action at this time.