mirror of
https://github.com/matrix-org/matrix-spec
synced 2026-01-03 14:38:37 +01:00
Merge pull request #143 from matrix-org/paul/federation-room-join
Document the federation remote join handshake
This commit is contained in:
commit
e95a1616af
|
|
@ -533,6 +533,164 @@ part of the path specifies the kind of query being made, and its query
|
|||
arguments have a meaning specific to that kind of query. The response is a
|
||||
JSON-encoded object whose meaning also depends on the kind of query.
|
||||
|
||||
|
||||
To join a room::
|
||||
|
||||
GET .../make_join/<room_id>/<user_id>
|
||||
Response: JSON encoding of a join proto-event
|
||||
|
||||
PUT .../send_join/<room_id>/<event_id>
|
||||
Response: JSON encoding of the state of the room at the time of the event
|
||||
|
||||
Performs the room join handshake. For more information, see "Joining Rooms"
|
||||
below.
|
||||
|
||||
Joining Rooms
|
||||
-------------
|
||||
|
||||
When a new user wishes to join room that the user's homeserver already knows
|
||||
about, the homeserver can immediately determine if this is allowable by
|
||||
inspecting the state of the room, and if it is acceptable, it can generate,
|
||||
sign, and emit a new ``m.room.member`` state event adding the user into that
|
||||
room. When the homeserver does not yet know about the room it cannot do this
|
||||
directly. Instead, it must take a longer multi-stage handshaking process by
|
||||
which it first selects a remote homeserver which is already participating in
|
||||
that room, and uses it to assist in the joining process. This is the remote
|
||||
join handshake.
|
||||
|
||||
This handshake involves the homeserver of the new member wishing to join
|
||||
(referred to here as the "joining" server), the directory server hosting the
|
||||
room alias the user is requesting to join with, and a homeserver where existing
|
||||
room members are already present (referred to as the "resident" server).
|
||||
|
||||
In summary, the remote join handshake consists of the joining server querying
|
||||
the directory server for information about the room alias; receiving a room ID
|
||||
and a list of join candidates. The joining server then requests information
|
||||
about the room from one of the residents. It uses this information to construct
|
||||
a ``m.room.member`` event which it finally sends to a resident server.
|
||||
|
||||
Conceptually these are three different roles of homeserver. In practice the
|
||||
directory server is likely to be resident in the room, and so may be selected
|
||||
by the joining server to be the assisting resident. Likewise, it is likely that
|
||||
the joining server picks the same candidate resident for both phases of event
|
||||
construction, though in principle any valid candidate may be used at each time.
|
||||
Thus, any join handshake can potentially involve anywhere from two to four
|
||||
homeservers, though most in practice will use just two.
|
||||
|
||||
::
|
||||
|
||||
Client Joining Directory Resident
|
||||
Server Server Server
|
||||
|
||||
join request -->
|
||||
|
|
||||
directory request ------->
|
||||
<---------- directory response
|
||||
|
|
||||
make_join request ----------------------->
|
||||
<------------------------------- make_join response
|
||||
|
|
||||
send_join request ----------------------->
|
||||
<------------------------------- send_join response
|
||||
|
|
||||
<---------- join response
|
||||
|
||||
The first part of the handshake usually involves using the directory server to
|
||||
request the room ID and join candidates. This is covered in more detail on the
|
||||
directory server documentation, below. In the case of a new user joining a
|
||||
room as a result of a received invite, the joining user's homeserver could
|
||||
optimise this step away by picking the origin server of that invite message as
|
||||
the join candidate. However, the joining server should be aware that the origin
|
||||
server of the invite might since have left the room, so should be prepared to
|
||||
fall back on the regular join flow if this optimisation fails.
|
||||
|
||||
Once the joining server has the room ID and the join candidates, it then needs
|
||||
to obtain enough information about the room to fill in the required fields of
|
||||
the ``m.room.member`` event. It obtains this by selecting a resident from the
|
||||
candidate list, and requesting the ``make_join`` endpoint using a ``GET``
|
||||
request, specifying the room ID and the user ID of the new member who is
|
||||
attempting to join.
|
||||
|
||||
The resident server replies to this request with a JSON-encoded object having a
|
||||
single key called ``event``; within this is an object whose fields contain some
|
||||
of the information that the joining server will need. Despite its name, this
|
||||
object is not a full event; notably it does not need to be hashed or signed by
|
||||
the resident homeserver. The required fields are:
|
||||
|
||||
==================== ======== ============
|
||||
Key Type Description
|
||||
==================== ======== ============
|
||||
``type`` String The value ``m.room.member``
|
||||
``auth_events`` List An event-reference list containing the
|
||||
authorization events that would allow this member
|
||||
to join
|
||||
``content`` Object The event content
|
||||
``depth`` Integer (this field must be present but is ignored; it
|
||||
may be 0)
|
||||
``event_id`` String A new event ID specified by the resident
|
||||
homeserver
|
||||
``origin`` String The name of the resident homeserver
|
||||
``origin_server_ts`` Integer A timestamp added by the resident homeserver
|
||||
``prev_events`` List An event-reference list containing the immediate
|
||||
predecessor events
|
||||
``room_id`` String The room ID of the room
|
||||
``sender`` String The user ID of the joining member
|
||||
``state_key`` String The user ID of the joining member
|
||||
==================== ======== ============
|
||||
|
||||
The ``content`` field itself must be an object, containing:
|
||||
|
||||
============== ====== ============
|
||||
Key Type Description
|
||||
============== ====== ============
|
||||
``membership`` String The value ``join``
|
||||
============== ====== ============
|
||||
|
||||
The joining server now has sufficient information to construct the real join
|
||||
event from these protoevent fields. It copies the values of most of them,
|
||||
adding (or replacing) the following fields:
|
||||
|
||||
==================== ======= ============
|
||||
Key Type Description
|
||||
==================== ======= ============
|
||||
``event_id`` String A new event ID specified by the joining homeserver
|
||||
``origin`` String The name of the joining homeserver
|
||||
``origin_server_ts`` Integer A timestamp added by the joining homeserver
|
||||
==================== ======= ============
|
||||
|
||||
.. TODO-spec
|
||||
- Why does the protoevent have an event_id, only for the real event to ignore
|
||||
it and specify a different one? We should definitely pick one or the other.
|
||||
|
||||
This will be a true event, so the joining server should apply the event-signing
|
||||
algorithm to it, resulting in the addition of the ``hashes`` and ``signatures``
|
||||
fields.
|
||||
|
||||
To complete the join handshake, the joining server must now submit this new
|
||||
event to an resident homeserver, by using the ``send_join`` endpoint. This is
|
||||
invoked using the room ID and the event ID of the new member event.
|
||||
|
||||
The resident homeserver then accepts this event into the room's event graph,
|
||||
and responds to the joining server with the full set of state for the newly-
|
||||
joined room. This is returned as a two-element list, whose first element is the
|
||||
integer 200, and whose second element is an object which contains the
|
||||
following keys:
|
||||
|
||||
============== ===== ============
|
||||
Key Type Description
|
||||
============== ===== ============
|
||||
``auth_chain`` List A list of events giving the authorization chain for this
|
||||
join event
|
||||
``state`` List A complete list of the prevailing state events at the
|
||||
instant just before accepting the new ``m.room.member``
|
||||
event
|
||||
============== ===== ============
|
||||
|
||||
.. TODO-spec
|
||||
- (paul) I don't really understand why the full auth_chain events are given
|
||||
here. What purpose does it serve expanding them out in full, when surely
|
||||
they'll appear in the state anyway?
|
||||
|
||||
Backfilling
|
||||
-----------
|
||||
.. NOTE::
|
||||
|
|
@ -763,6 +921,7 @@ Querying directory information::
|
|||
servers: list of strings giving the join candidates
|
||||
|
||||
The list of join candidates is a list of server names that are likely to hold
|
||||
the given room; these are servers that the requesting server may wish to try
|
||||
joining with. This list may or may not include the server answering the query.
|
||||
the given room; these are servers that the requesting server may wish to use as
|
||||
resident servers as part of the remote join handshake. This list may or may not
|
||||
include the server answering the query.
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue