diff options
author | Junio C Hamano <gitster@pobox.com> | 2017-12-06 09:23:44 -0800 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2017-12-06 09:23:44 -0800 |
commit | 4c6dad0059b2b5d1ea996ccf67f93224955b07b4 (patch) | |
tree | c873cad90875dc679c722beac0abe4ddae5d25cb /daemon.c | |
parent | Merge branch 'sp/doc-info-attributes' (diff) | |
parent | Documentation: document Extra Parameters (diff) | |
download | tgif-4c6dad0059b2b5d1ea996ccf67f93224955b07b4.tar.xz |
Merge branch 'bw/protocol-v1'
A new mechanism to upgrade the wire protocol in place is proposed
and demonstrated that it works with the older versions of Git
without harming them.
* bw/protocol-v1:
Documentation: document Extra Parameters
ssh: introduce a 'simple' ssh variant
i5700: add interop test for protocol transition
http: tell server that the client understands v1
connect: tell server that the client understands v1
connect: teach client to recognize v1 server response
upload-pack, receive-pack: introduce protocol version 1
daemon: recognize hidden request arguments
protocol: introduce protocol extension mechanisms
pkt-line: add packet_write function
connect: in ref advertisement, shallows are last
Diffstat (limited to 'daemon.c')
-rw-r--r-- | daemon.c | 71 |
1 files changed, 62 insertions, 9 deletions
@@ -282,7 +282,7 @@ static const char *path_ok(const char *directory, struct hostinfo *hi) return NULL; /* Fallthrough. Deny by default */ } -typedef int (*daemon_service_fn)(void); +typedef int (*daemon_service_fn)(const struct argv_array *env); struct daemon_service { const char *name; const char *config_name; @@ -363,7 +363,7 @@ error_return: } static int run_service(const char *dir, struct daemon_service *service, - struct hostinfo *hi) + struct hostinfo *hi, const struct argv_array *env) { const char *path; int enabled = service->enabled; @@ -422,7 +422,7 @@ static int run_service(const char *dir, struct daemon_service *service, */ signal(SIGTERM, SIG_IGN); - return service->fn(); + return service->fn(env); } static void copy_to_log(int fd) @@ -462,25 +462,34 @@ static int run_service_command(struct child_process *cld) return finish_command(cld); } -static int upload_pack(void) +static int upload_pack(const struct argv_array *env) { struct child_process cld = CHILD_PROCESS_INIT; argv_array_pushl(&cld.args, "upload-pack", "--strict", NULL); argv_array_pushf(&cld.args, "--timeout=%u", timeout); + + argv_array_pushv(&cld.env_array, env->argv); + return run_service_command(&cld); } -static int upload_archive(void) +static int upload_archive(const struct argv_array *env) { struct child_process cld = CHILD_PROCESS_INIT; argv_array_push(&cld.args, "upload-archive"); + + argv_array_pushv(&cld.env_array, env->argv); + return run_service_command(&cld); } -static int receive_pack(void) +static int receive_pack(const struct argv_array *env) { struct child_process cld = CHILD_PROCESS_INIT; argv_array_push(&cld.args, "receive-pack"); + + argv_array_pushv(&cld.env_array, env->argv); + return run_service_command(&cld); } @@ -573,8 +582,11 @@ static void canonicalize_client(struct strbuf *out, const char *in) /* * Read the host as supplied by the client connection. + * + * Returns a pointer to the character after the NUL byte terminating the host + * arguemnt, or 'extra_args' if there is no host arguemnt. */ -static void parse_host_arg(struct hostinfo *hi, char *extra_args, int buflen) +static char *parse_host_arg(struct hostinfo *hi, char *extra_args, int buflen) { char *val; int vallen; @@ -602,6 +614,43 @@ static void parse_host_arg(struct hostinfo *hi, char *extra_args, int buflen) if (extra_args < end && *extra_args) die("Invalid request"); } + + return extra_args; +} + +static void parse_extra_args(struct hostinfo *hi, struct argv_array *env, + char *extra_args, int buflen) +{ + const char *end = extra_args + buflen; + struct strbuf git_protocol = STRBUF_INIT; + + /* First look for the host argument */ + extra_args = parse_host_arg(hi, extra_args, buflen); + + /* Look for additional arguments places after a second NUL byte */ + for (; extra_args < end; extra_args += strlen(extra_args) + 1) { + const char *arg = extra_args; + + /* + * Parse the extra arguments, adding most to 'git_protocol' + * which will be used to set the 'GIT_PROTOCOL' envvar in the + * service that will be run. + * + * If there ends up being a particular arg in the future that + * git-daemon needs to parse specificly (like the 'host' arg) + * then it can be parsed here and not added to 'git_protocol'. + */ + if (*arg) { + if (git_protocol.len > 0) + strbuf_addch(&git_protocol, ':'); + strbuf_addstr(&git_protocol, arg); + } + } + + if (git_protocol.len > 0) + argv_array_pushf(env, GIT_PROTOCOL_ENVIRONMENT "=%s", + git_protocol.buf); + strbuf_release(&git_protocol); } /* @@ -695,6 +744,7 @@ static int execute(void) int pktlen, len, i; char *addr = getenv("REMOTE_ADDR"), *port = getenv("REMOTE_PORT"); struct hostinfo hi; + struct argv_array env = ARGV_ARRAY_INIT; hostinfo_init(&hi); @@ -716,8 +766,9 @@ static int execute(void) pktlen--; } + /* parse additional args hidden behind a NUL byte */ if (len != pktlen) - parse_host_arg(&hi, line + len + 1, pktlen - len - 1); + parse_extra_args(&hi, &env, line + len + 1, pktlen - len - 1); for (i = 0; i < ARRAY_SIZE(daemon_service); i++) { struct daemon_service *s = &(daemon_service[i]); @@ -730,13 +781,15 @@ static int execute(void) * Note: The directory here is probably context sensitive, * and might depend on the actual service being performed. */ - int rc = run_service(arg, s, &hi); + int rc = run_service(arg, s, &hi, &env); hostinfo_clear(&hi); + argv_array_clear(&env); return rc; } } hostinfo_clear(&hi); + argv_array_clear(&env); logerror("Protocol error: '%s'", line); return -1; } |