Skip to content

Commit

Permalink
Merge branch 'js/trace2-session-id'
Browse files Browse the repository at this point in the history
The transport layer was taught to optionally exchange the session
ID assigned by the trace2 subsystem during fetch/push transactions.

* js/trace2-session-id:
  receive-pack: log received client session ID
  send-pack: advertise session ID in capabilities
  upload-pack, serve: log received client session ID
  fetch-pack: advertise session ID in capabilities
  transport: log received server session ID
  serve: advertise session ID in v2 capabilities
  receive-pack: advertise session ID in v0 capabilities
  upload-pack: advertise session ID in v0 capabilities
  trace2: add a public function for getting the SID
  docs: new transfer.advertiseSID option
  docs: new capability to advertise session IDs
  • Loading branch information
gitster committed Dec 8, 2020
2 parents 9b3b4ad + a2a066d commit 01b8886
Show file tree
Hide file tree
Showing 12 changed files with 198 additions and 3 deletions.
4 changes: 4 additions & 0 deletions Documentation/config/transfer.txt
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,7 @@ transfer.unpackLimit::
When `fetch.unpackLimit` or `receive.unpackLimit` are
not set, the value of this variable is used instead.
The default value is 100.

transfer.advertiseSID::
Boolean. When true, client and server processes will advertise their
unique session IDs to their remote counterpart. Defaults to false.
17 changes: 15 additions & 2 deletions Documentation/technical/protocol-capabilities.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ and 'push-cert' capabilities are sent and recognized by the receive-pack
(push to server) process.

The 'ofs-delta' and 'side-band-64k' capabilities are sent and recognized
by both upload-pack and receive-pack protocols. The 'agent' capability
may optionally be sent in both protocols.
by both upload-pack and receive-pack protocols. The 'agent' and 'session-id'
capabilities may optionally be sent in both protocols.

All other capabilities are only recognized by the upload-pack (fetch
from server) process.
Expand Down Expand Up @@ -365,3 +365,16 @@ If the upload-pack server advertises the 'filter' capability,
fetch-pack may send "filter" commands to request a partial clone
or partial fetch and request that the server omit various objects
from the packfile.

session-id=<session id>
-----------------------

The server may advertise a session ID that can be used to identify this process
across multiple requests. The client may advertise its own session ID back to
the server as well.

Session IDs should be unique to a given process. They must fit within a
packet-line, and must not contain non-printable or whitespace characters. The
current implementation uses trace2 session IDs (see
link:api-trace2.html[api-trace2] for details), but this may change and users of
the session ID should not rely on this fact.
13 changes: 13 additions & 0 deletions Documentation/technical/protocol-v2.txt
Original file line number Diff line number Diff line change
Expand Up @@ -492,3 +492,16 @@ form `object-format=X`) to notify the client that the server is able to deal
with objects using hash algorithm X. If not specified, the server is assumed to
only handle SHA-1. If the client would like to use a hash algorithm other than
SHA-1, it should specify its object-format string.

session-id=<session id>
~~~~~~~~~~~~~~~~~~~~~~~

The server may advertise a session ID that can be used to identify this process
across multiple requests. The client may advertise its own session ID back to
the server as well.

Session IDs should be unique to a given process. They must fit within a
packet-line, and must not contain non-printable or whitespace characters. The
current implementation uses trace2 session IDs (see
link:api-trace2.html[api-trace2] for details), but this may change and users of
the session ID should not rely on this fact.
15 changes: 15 additions & 0 deletions builtin/receive-pack.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ static int receive_unpack_limit = -1;
static int transfer_unpack_limit = -1;
static int advertise_atomic_push = 1;
static int advertise_push_options;
static int advertise_sid;
static int unpack_limit = 100;
static off_t max_input_size;
static int report_status;
Expand Down Expand Up @@ -248,6 +249,11 @@ static int receive_pack_config(const char *var, const char *value, void *cb)
return 0;
}

if (strcmp(var, "transfer.advertisesid") == 0) {
advertise_sid = git_config_bool(var, value);
return 0;
}

return git_default_config(var, value, cb);
}

Expand All @@ -268,6 +274,8 @@ static void show_ref(const char *path, const struct object_id *oid)
strbuf_addf(&cap, " push-cert=%s", push_cert_nonce);
if (advertise_push_options)
strbuf_addstr(&cap, " push-options");
if (advertise_sid)
strbuf_addf(&cap, " session-id=%s", trace2_session_id());
strbuf_addf(&cap, " object-format=%s", the_hash_algo->name);
strbuf_addf(&cap, " agent=%s", git_user_agent_sanitized());
packet_write_fmt(1, "%s %s%c%s\n",
Expand Down Expand Up @@ -2075,6 +2083,7 @@ static struct command *read_head_info(struct packet_reader *reader,
if (linelen < reader->pktlen) {
const char *feature_list = reader->line + linelen + 1;
const char *hash = NULL;
const char *client_sid;
int len = 0;
if (parse_feature_request(feature_list, "report-status"))
report_status = 1;
Expand All @@ -2097,6 +2106,12 @@ static struct command *read_head_info(struct packet_reader *reader,
}
if (xstrncmpz(the_hash_algo->name, hash, len))
die("error: unsupported object format '%s'", hash);
client_sid = parse_feature_value(feature_list, "session-id", &len, NULL);
if (client_sid) {
char *sid = xstrndup(client_sid, len);
trace2_data_string("transfer", NULL, "client-sid", client_sid);
free(sid);
}
}

if (!strcmp(reader->line, "push-cert")) {
Expand Down
9 changes: 9 additions & 0 deletions fetch-pack.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ static int fetch_fsck_objects = -1;
static int transfer_fsck_objects = -1;
static int agent_supported;
static int server_supports_filtering;
static int advertise_sid;
static struct shallow_lock shallow_lock;
static const char *alternate_shallow_file;
static struct strbuf fsck_msg_types = STRBUF_INIT;
Expand Down Expand Up @@ -326,6 +327,8 @@ static int find_common(struct fetch_negotiator *negotiator,
if (deepen_not_ok) strbuf_addstr(&c, " deepen-not");
if (agent_supported) strbuf_addf(&c, " agent=%s",
git_user_agent_sanitized());
if (advertise_sid)
strbuf_addf(&c, " session-id=%s", trace2_session_id());
if (args->filter_options.choice)
strbuf_addstr(&c, " filter");
packet_buf_write(&req_buf, "want %s%s\n", remote_hex, c.buf);
Expand Down Expand Up @@ -979,6 +982,9 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
agent_len, agent_feature);
}

if (!server_supports("session-id"))
advertise_sid = 0;

if (server_supports("shallow"))
print_verbose(args, _("Server supports %s"), "shallow");
else if (args->depth > 0 || is_repository_shallow(r))
Expand Down Expand Up @@ -1191,6 +1197,8 @@ static int send_fetch_request(struct fetch_negotiator *negotiator, int fd_out,
packet_buf_write(&req_buf, "command=fetch");
if (server_supports_v2("agent", 0))
packet_buf_write(&req_buf, "agent=%s", git_user_agent_sanitized());
if (advertise_sid && server_supports_v2("session-id", 0))
packet_buf_write(&req_buf, "session-id=%s", trace2_session_id());
if (args->server_options && args->server_options->nr &&
server_supports_v2("server-option", 1)) {
int i;
Expand Down Expand Up @@ -1711,6 +1719,7 @@ static void fetch_pack_config(void)
git_config_get_bool("repack.usedeltabaseoffset", &prefer_ofs_delta);
git_config_get_bool("fetch.fsckobjects", &fetch_fsck_objects);
git_config_get_bool("transfer.fsckobjects", &transfer_fsck_objects);
git_config_get_bool("transfer.advertisesid", &advertise_sid);
if (!uri_protocols.nr) {
char *str;

Expand Down
7 changes: 7 additions & 0 deletions send-pack.c
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,7 @@ int send_pack(struct send_pack_args *args,
int use_sideband = 0;
int quiet_supported = 0;
int agent_supported = 0;
int advertise_sid = 0;
int use_atomic = 0;
int atomic_supported = 0;
int use_push_options = 0;
Expand All @@ -436,6 +437,8 @@ int send_pack(struct send_pack_args *args,
const char *push_cert_nonce = NULL;
struct packet_reader reader;

git_config_get_bool("transfer.advertisesid", &advertise_sid);

/* Does the other end support the reporting? */
if (server_supports("report-status-v2"))
status_report = 2;
Expand All @@ -451,6 +454,8 @@ int send_pack(struct send_pack_args *args,
quiet_supported = 1;
if (server_supports("agent"))
agent_supported = 1;
if (!server_supports("session-id"))
advertise_sid = 0;
if (server_supports("no-thin"))
args->use_thin_pack = 0;
if (server_supports("atomic"))
Expand Down Expand Up @@ -507,6 +512,8 @@ int send_pack(struct send_pack_args *args,
strbuf_addf(&cap_buf, " object-format=%s", the_hash_algo->name);
if (agent_supported)
strbuf_addf(&cap_buf, " agent=%s", git_user_agent_sanitized());
if (advertise_sid)
strbuf_addf(&cap_buf, " session-id=%s", trace2_session_id());

/*
* NEEDSWORK: why does delete-refs have to be so specific to
Expand Down
18 changes: 18 additions & 0 deletions serve.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include "serve.h"
#include "upload-pack.h"

static int advertise_sid;

static int always_advertise(struct repository *r,
struct strbuf *value)
{
Expand All @@ -30,6 +32,15 @@ static int object_format_advertise(struct repository *r,
return 1;
}

static int session_id_advertise(struct repository *r, struct strbuf *value)
{
if (!advertise_sid)
return 0;
if (value)
strbuf_addstr(value, trace2_session_id());
return 1;
}

struct protocol_capability {
/*
* The name of the capability. The server uses this name when
Expand Down Expand Up @@ -66,6 +77,7 @@ static struct protocol_capability capabilities[] = {
{ "fetch", upload_pack_advertise, upload_pack_v2 },
{ "server-option", always_advertise, NULL },
{ "object-format", object_format_advertise, NULL },
{ "session-id", session_id_advertise, NULL },
};

static void advertise_capabilities(void)
Expand Down Expand Up @@ -189,6 +201,7 @@ static int process_request(void)
struct packet_reader reader;
struct strvec keys = STRVEC_INIT;
struct protocol_capability *command = NULL;
const char *client_sid;

packet_reader_init(&reader, 0, NULL, 0,
PACKET_READ_CHOMP_NEWLINE |
Expand Down Expand Up @@ -252,6 +265,9 @@ static int process_request(void)

check_algorithm(the_repository, &keys);

if (has_capability(&keys, "session-id", &client_sid))
trace2_data_string("transfer", NULL, "client-sid", client_sid);

command->command(the_repository, &keys, &reader);

strvec_clear(&keys);
Expand All @@ -261,6 +277,8 @@ static int process_request(void)
/* Main serve loop for protocol version 2 */
void serve(struct serve_options *options)
{
git_config_get_bool("transfer.advertisesid", &advertise_sid);

if (options->advertise_capabilities || !options->stateless_rpc) {
/* serve by default supports v2 */
packet_write_fmt(1, "version 2\n");
Expand Down
78 changes: 78 additions & 0 deletions t/t5705-session-id-in-capabilities.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#!/bin/sh

test_description='session ID in capabilities'

. ./test-lib.sh

REPO="$(pwd)/repo"
LOCAL_PRISTINE="$(pwd)/local_pristine"

test_expect_success 'setup repos for session ID capability tests' '
git init "$REPO" &&
test_commit -C "$REPO" a &&
git clone "file://$REPO" "$LOCAL_PRISTINE" &&
test_commit -C "$REPO" b
'

for PROTO in 0 1 2
do
test_expect_success "session IDs not advertised by default (fetch v${PROTO})" '
test_when_finished "rm -rf local tr2-client-events tr2-server-events" &&
cp -r "$LOCAL_PRISTINE" local &&
GIT_TRACE2_EVENT="$(pwd)/tr2-client-events" \
git -c protocol.version=$PROTO -C local fetch \
--upload-pack "GIT_TRACE2_EVENT=\"$(pwd)/tr2-server-events\" git-upload-pack" \
origin &&
test -z "$(grep \"key\":\"server-sid\" tr2-client-events)" &&
test -z "$(grep \"key\":\"client-sid\" tr2-server-events)"
'

test_expect_success "session IDs not advertised by default (push v${PROTO})" '
test_when_finished "rm -rf local tr2-client-events tr2-server-events" &&
test_when_finished "git -C local push --delete origin new-branch" &&
cp -r "$LOCAL_PRISTINE" local &&
git -C local pull --no-rebase origin &&
GIT_TRACE2_EVENT_NESTING=5 \
GIT_TRACE2_EVENT="$(pwd)/tr2-client-events" \
git -c protocol.version=$PROTO -C local push \
--receive-pack "GIT_TRACE2_EVENT=\"$(pwd)/tr2-server-events\" git-receive-pack" \
origin HEAD:new-branch &&
test -z "$(grep \"key\":\"server-sid\" tr2-client-events)" &&
test -z "$(grep \"key\":\"client-sid\" tr2-server-events)"
'
done

test_expect_success 'enable SID advertisement' '
git -C "$REPO" config transfer.advertiseSID true &&
git -C "$LOCAL_PRISTINE" config transfer.advertiseSID true
'

for PROTO in 0 1 2
do
test_expect_success "session IDs advertised (fetch v${PROTO})" '
test_when_finished "rm -rf local tr2-client-events tr2-server-events" &&
cp -r "$LOCAL_PRISTINE" local &&
GIT_TRACE2_EVENT="$(pwd)/tr2-client-events" \
git -c protocol.version=$PROTO -C local fetch \
--upload-pack "GIT_TRACE2_EVENT=\"$(pwd)/tr2-server-events\" git-upload-pack" \
origin &&
grep \"key\":\"server-sid\" tr2-client-events &&
grep \"key\":\"client-sid\" tr2-server-events
'

test_expect_success "session IDs advertised (push v${PROTO})" '
test_when_finished "rm -rf local tr2-client-events tr2-server-events" &&
test_when_finished "git -C local push --delete origin new-branch" &&
cp -r "$LOCAL_PRISTINE" local &&
git -C local pull --no-rebase origin &&
GIT_TRACE2_EVENT_NESTING=5 \
GIT_TRACE2_EVENT="$(pwd)/tr2-client-events" \
git -c protocol.version=$PROTO -C local push \
--receive-pack "GIT_TRACE2_EVENT=\"$(pwd)/tr2-server-events\" git-receive-pack" \
origin HEAD:new-branch &&
grep \"key\":\"server-sid\" tr2-client-events &&
grep \"key\":\"client-sid\" tr2-server-events
'
done

test_done
5 changes: 5 additions & 0 deletions trace2.c
Original file line number Diff line number Diff line change
Expand Up @@ -792,3 +792,8 @@ void trace2_printf(const char *fmt, ...)
va_end(ap);
}
#endif

const char *trace2_session_id(void)
{
return tr2_sid_get();
}
2 changes: 2 additions & 0 deletions trace2.h
Original file line number Diff line number Diff line change
Expand Up @@ -500,4 +500,6 @@ void trace2_collect_process_info(enum trace2_process_info_reason reason);
} while (0)
#endif

const char *trace2_session_id(void);

#endif /* TRACE2_H */
10 changes: 10 additions & 0 deletions transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,8 @@ static struct ref *handshake(struct transport *transport, int for_push,
struct git_transport_data *data = transport->data;
struct ref *refs = NULL;
struct packet_reader reader;
int sid_len;
const char *server_sid;

connect_setup(transport, for_push);

Expand All @@ -297,6 +299,8 @@ static struct ref *handshake(struct transport *transport, int for_push,
data->version = discover_version(&reader);
switch (data->version) {
case protocol_v2:
if (server_feature_v2("session-id", &server_sid))
trace2_data_string("transfer", NULL, "server-sid", server_sid);
if (must_list_refs)
get_remote_refs(data->fd[1], &reader, &refs, for_push,
ref_prefixes,
Expand All @@ -310,6 +314,12 @@ static struct ref *handshake(struct transport *transport, int for_push,
for_push ? REF_NORMAL : 0,
&data->extra_have,
&data->shallow);
server_sid = server_feature_value("session-id", &sid_len);
if (server_sid) {
char *sid = xstrndup(server_sid, sid_len);
trace2_data_string("transfer", NULL, "server-sid", sid);
free(sid);
}
break;
case protocol_unknown_version:
BUG("unknown protocol version");
Expand Down

0 comments on commit 01b8886

Please sign in to comment.