Merge pull request #143 from matrix-org/paul/federation-room-join

Document the federation remote join handshake
pull/977/head
Paul Evans 9 years ago
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…
Cancel
Save