Merge branch 'js/trace2-session-id'
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
This commit is contained in:
commit
01b8886a62
@ -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.
|
||||
|
@ -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.
|
||||
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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",
|
||||
@ -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;
|
||||
@ -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")) {
|
||||
|
@ -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;
|
||||
@ -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);
|
||||
@ -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))
|
||||
@ -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;
|
||||
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
@ -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;
|
||||
@ -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"))
|
||||
@ -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
|
||||
|
18
serve.c
18
serve.c
@ -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)
|
||||
{
|
||||
@ -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
|
||||
@ -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)
|
||||
@ -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 |
|
||||
@ -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);
|
||||
@ -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");
|
||||
|
78
t/t5705-session-id-in-capabilities.sh
Executable file
78
t/t5705-session-id-in-capabilities.sh
Executable file
@ -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
trace2.c
5
trace2.c
@ -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
trace2.h
2
trace2.h
@ -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
transport.c
10
transport.c
@ -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);
|
||||
|
||||
@ -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,
|
||||
@ -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");
|
||||
|
@ -110,6 +110,7 @@ struct upload_pack_data {
|
||||
unsigned done : 1; /* v2 only */
|
||||
unsigned allow_ref_in_want : 1; /* v2 only */
|
||||
unsigned allow_sideband_all : 1; /* v2 only */
|
||||
unsigned advertise_sid : 1;
|
||||
};
|
||||
|
||||
static void upload_pack_data_init(struct upload_pack_data *data)
|
||||
@ -141,6 +142,7 @@ static void upload_pack_data_init(struct upload_pack_data *data)
|
||||
packet_writer_init(&data->writer, 1);
|
||||
|
||||
data->keepalive = 5;
|
||||
data->advertise_sid = 0;
|
||||
}
|
||||
|
||||
static void upload_pack_data_clear(struct upload_pack_data *data)
|
||||
@ -1057,6 +1059,7 @@ static void receive_needs(struct upload_pack_data *data,
|
||||
const char *features;
|
||||
struct object_id oid_buf;
|
||||
const char *arg;
|
||||
int feature_len;
|
||||
|
||||
reset_timeout(data->timeout);
|
||||
if (packet_reader_read(reader) != PACKET_READ_NORMAL)
|
||||
@ -1109,6 +1112,13 @@ static void receive_needs(struct upload_pack_data *data,
|
||||
parse_feature_request(features, "filter"))
|
||||
data->filter_capability_requested = 1;
|
||||
|
||||
arg = parse_feature_value(features, "session-id", &feature_len, NULL);
|
||||
if (arg) {
|
||||
char *client_sid = xstrndup(arg, feature_len);
|
||||
trace2_data_string("transfer", NULL, "client-sid", client_sid);
|
||||
free(client_sid);
|
||||
}
|
||||
|
||||
o = parse_object(the_repository, &oid_buf);
|
||||
if (!o) {
|
||||
packet_writer_error(&data->writer,
|
||||
@ -1179,6 +1189,11 @@ static void format_symref_info(struct strbuf *buf, struct string_list *symref)
|
||||
strbuf_addf(buf, " symref=%s:%s", item->string, (char *)item->util);
|
||||
}
|
||||
|
||||
static void format_session_id(struct strbuf *buf, struct upload_pack_data *d) {
|
||||
if (d->advertise_sid)
|
||||
strbuf_addf(buf, " session-id=%s", trace2_session_id());
|
||||
}
|
||||
|
||||
static int send_ref(const char *refname, const struct object_id *oid,
|
||||
int flag, void *cb_data)
|
||||
{
|
||||
@ -1194,9 +1209,11 @@ static int send_ref(const char *refname, const struct object_id *oid,
|
||||
|
||||
if (capabilities) {
|
||||
struct strbuf symref_info = STRBUF_INIT;
|
||||
struct strbuf session_id = STRBUF_INIT;
|
||||
|
||||
format_symref_info(&symref_info, &data->symref);
|
||||
packet_write_fmt(1, "%s %s%c%s%s%s%s%s%s object-format=%s agent=%s\n",
|
||||
format_session_id(&session_id, data);
|
||||
packet_write_fmt(1, "%s %s%c%s%s%s%s%s%s%s object-format=%s agent=%s\n",
|
||||
oid_to_hex(oid), refname_nons,
|
||||
0, capabilities,
|
||||
(data->allow_uor & ALLOW_TIP_SHA1) ?
|
||||
@ -1206,9 +1223,11 @@ static int send_ref(const char *refname, const struct object_id *oid,
|
||||
data->stateless_rpc ? " no-done" : "",
|
||||
symref_info.buf,
|
||||
data->allow_filter ? " filter" : "",
|
||||
session_id.buf,
|
||||
the_hash_algo->name,
|
||||
git_user_agent_sanitized());
|
||||
strbuf_release(&symref_info);
|
||||
strbuf_release(&session_id);
|
||||
} else {
|
||||
packet_write_fmt(1, "%s %s\n", oid_to_hex(oid), refname_nons);
|
||||
}
|
||||
@ -1300,6 +1319,8 @@ static int upload_pack_config(const char *var, const char *value, void *cb_data)
|
||||
data->allow_sideband_all = git_config_bool(var, value);
|
||||
} else if (!strcmp("core.precomposeunicode", var)) {
|
||||
precomposed_unicode = git_config_bool(var, value);
|
||||
} else if (!strcmp("transfer.advertisesid", var)) {
|
||||
data->advertise_sid = git_config_bool(var, value);
|
||||
}
|
||||
|
||||
if (current_config_scope() != CONFIG_SCOPE_LOCAL &&
|
||||
|
Loading…
Reference in New Issue
Block a user