2 #include "repository.h"
 
   6 #include "argv-array.h"
 
   9 #include "upload-pack.h"
 
  11 static int always_advertise(struct repository *r,
 
  17 static int agent_advertise(struct repository *r,
 
  21                 strbuf_addstr(value, git_user_agent_sanitized());
 
  25 struct protocol_capability {
 
  27          * The name of the capability.  The server uses this name when
 
  28          * advertising this capability, and the client uses this name to
 
  29          * specify this capability.
 
  34          * Function queried to see if a capability should be advertised.
 
  35          * Optionally a value can be specified by adding it to 'value'.
 
  36          * If a value is added to 'value', the server will advertise this
 
  37          * capability as "<name>=<value>" instead of "<name>".
 
  39         int (*advertise)(struct repository *r, struct strbuf *value);
 
  42          * Function called when a client requests the capability as a command.
 
  43          * The function will be provided the capabilities requested via 'keys'
 
  44          * as well as a struct packet_reader 'request' which the command should
 
  45          * use to read the command specific part of the request.  Every command
 
  46          * MUST read until a flush packet is seen before sending a response.
 
  48          * This field should be NULL for capabilities which are not commands.
 
  50         int (*command)(struct repository *r,
 
  51                        struct argv_array *keys,
 
  52                        struct packet_reader *request);
 
  55 static struct protocol_capability capabilities[] = {
 
  56         { "agent", agent_advertise, NULL },
 
  57         { "ls-refs", always_advertise, ls_refs },
 
  58         { "fetch", upload_pack_advertise, upload_pack_v2 },
 
  59         { "server-option", always_advertise, NULL },
 
  62 static void advertise_capabilities(void)
 
  64         struct strbuf capability = STRBUF_INIT;
 
  65         struct strbuf value = STRBUF_INIT;
 
  68         for (i = 0; i < ARRAY_SIZE(capabilities); i++) {
 
  69                 struct protocol_capability *c = &capabilities[i];
 
  71                 if (c->advertise(the_repository, &value)) {
 
  72                         strbuf_addstr(&capability, c->name);
 
  75                                 strbuf_addch(&capability, '=');
 
  76                                 strbuf_addbuf(&capability, &value);
 
  79                         strbuf_addch(&capability, '\n');
 
  80                         packet_write(1, capability.buf, capability.len);
 
  83                 strbuf_reset(&capability);
 
  88         strbuf_release(&capability);
 
  89         strbuf_release(&value);
 
  92 static struct protocol_capability *get_capability(const char *key)
 
  99         for (i = 0; i < ARRAY_SIZE(capabilities); i++) {
 
 100                 struct protocol_capability *c = &capabilities[i];
 
 102                 if (skip_prefix(key, c->name, &out) && (!*out || *out == '='))
 
 109 static int is_valid_capability(const char *key)
 
 111         const struct protocol_capability *c = get_capability(key);
 
 113         return c && c->advertise(the_repository, NULL);
 
 116 static int is_command(const char *key, struct protocol_capability **command)
 
 120         if (skip_prefix(key, "command=", &out)) {
 
 121                 struct protocol_capability *cmd = get_capability(out);
 
 124                         die("command '%s' requested after already requesting command '%s'",
 
 125                             out, (*command)->name);
 
 126                 if (!cmd || !cmd->advertise(the_repository, NULL) || !cmd->command)
 
 127                         die("invalid command '%s'", out);
 
 136 int has_capability(const struct argv_array *keys, const char *capability,
 
 140         for (i = 0; i < keys->argc; i++) {
 
 142                 if (skip_prefix(keys->argv[i], capability, &out) &&
 
 143                     (!*out || *out == '=')) {
 
 157         PROCESS_REQUEST_KEYS,
 
 158         PROCESS_REQUEST_DONE,
 
 161 static int process_request(void)
 
 163         enum request_state state = PROCESS_REQUEST_KEYS;
 
 164         struct packet_reader reader;
 
 165         struct argv_array keys = ARGV_ARRAY_INIT;
 
 166         struct protocol_capability *command = NULL;
 
 168         packet_reader_init(&reader, 0, NULL, 0,
 
 169                            PACKET_READ_CHOMP_NEWLINE |
 
 170                            PACKET_READ_GENTLE_ON_EOF |
 
 171                            PACKET_READ_DIE_ON_ERR_PACKET);
 
 174          * Check to see if the client closed their end before sending another
 
 175          * request.  If so we can terminate the connection.
 
 177         if (packet_reader_peek(&reader) == PACKET_READ_EOF)
 
 179         reader.options &= ~PACKET_READ_GENTLE_ON_EOF;
 
 181         while (state != PROCESS_REQUEST_DONE) {
 
 182                 switch (packet_reader_peek(&reader)) {
 
 183                 case PACKET_READ_EOF:
 
 184                         BUG("Should have already died when seeing EOF");
 
 185                 case PACKET_READ_NORMAL:
 
 186                         /* collect request; a sequence of keys and values */
 
 187                         if (is_command(reader.line, &command) ||
 
 188                             is_valid_capability(reader.line))
 
 189                                 argv_array_push(&keys, reader.line);
 
 191                                 die("unknown capability '%s'", reader.line);
 
 193                         /* Consume the peeked line */
 
 194                         packet_reader_read(&reader);
 
 196                 case PACKET_READ_FLUSH:
 
 198                          * If no command and no keys were given then the client
 
 199                          * wanted to terminate the connection.
 
 205                          * The flush packet isn't consume here like it is in
 
 206                          * the other parts of this switch statement.  This is
 
 207                          * so that the command can read the flush packet and
 
 208                          * see the end of the request in the same way it would
 
 209                          * if command specific arguments were provided after a
 
 212                         state = PROCESS_REQUEST_DONE;
 
 214                 case PACKET_READ_DELIM:
 
 215                         /* Consume the peeked line */
 
 216                         packet_reader_read(&reader);
 
 218                         state = PROCESS_REQUEST_DONE;
 
 224                 die("no command requested");
 
 226         command->command(the_repository, &keys, &reader);
 
 228         argv_array_clear(&keys);
 
 232 /* Main serve loop for protocol version 2 */
 
 233 void serve(struct serve_options *options)
 
 235         if (options->advertise_capabilities || !options->stateless_rpc) {
 
 236                 /* serve by default supports v2 */
 
 237                 packet_write_fmt(1, "version 2\n");
 
 239                 advertise_capabilities();
 
 241                  * If only the list of capabilities was requested exit
 
 242                  * immediately after advertising capabilities
 
 244                 if (options->advertise_capabilities)
 
 249          * If stateless-rpc was requested then exit after
 
 250          * a single request/response exchange
 
 252         if (options->stateless_rpc) {
 
 256                         if (process_request())