69 lines
3.0 KiB
Markdown
69 lines
3.0 KiB
Markdown
# MSC4094: Sync Server and Client Times with endpoint
|
|
|
|
Some functionality in matrix depend on all clients local clocks being in sync.
|
|
Examples are:
|
|
|
|
- Call Member event expiration is computed by the its actual
|
|
age (`now - create-timestamp`). For this to work `now` and `create-timestamp`
|
|
need to be generated by synced clocks.
|
|
- The verification process uses timeouts to ignore old/expired requests.
|
|
- Legacy calls rely on synced clocks to ignore timed out ringing and connection
|
|
events.
|
|
- The call notify (matrixRTC calling) events also rely on expiration so the
|
|
receiving client only rings when the notify was just sent.
|
|
|
|
Currently events contain an `age` property in the unsigned field. This
|
|
accumulates the age by adding the intervals the event stayed on the servers.
|
|
Its a quiet complex system and is currently (as of January 2024) broken over Federation.
|
|
|
|
It is a complex system but solves the problem even it the Homeserver clocks are
|
|
not in sync.
|
|
|
|
A much simpler approach could be taken if the spec enforces Homeservers to sync
|
|
only be spec compliant if their clocks are in sync.
|
|
|
|
## Proposal
|
|
When all homeservers have set up their clock correctly the `origin-server-ts` can
|
|
be trusted while the event gets shared over federation.
|
|
|
|
The only problem left is the synchronization between the client and the server.
|
|
Only a single offset value (in ms) is required to compute correct server
|
|
timestamps. There is no necessity in sharing this information with each event (as
|
|
we currently do in `unsigned.age`).
|
|
Instead the homeserver exposes:
|
|
### `GET /_matrix/client/v3/get_server_now`
|
|
endpoint that returns the
|
|
current homeserver timestamp. A client has to fetch this endpoint
|
|
|
|
- when the local clock changes,
|
|
- any computation that evaluates the expiration of events is executed,
|
|
- an event is created and sent to the server with a field that contains information
|
|
based on a timestamp.
|
|
|
|
the last two cases can be omitted in case the client decides to cache the offset
|
|
between the local clock and the server clock.
|
|
This is the recommended implementation.
|
|
|
|
Another advantage is that this approach allows to know the offset between server
|
|
and client time beforehand.
|
|
In a scenario where the client wants to compute the expiration timestamp locally
|
|
the client needs to receive an event first to get the `unsigned.age` and the `origin_server_ts`
|
|
to then allow to compute a future timestamp on a synced clock.
|
|
|
|
## Potential issues
|
|
|
|
It relies on all homeservers configuring their clocks correctly.
|
|
In case they don't, expirations will happen at the wrong time.
|
|
|
|
## Alternatives
|
|
|
|
Sticking with the `unsigned.age` approach would solve the same problem but with
|
|
greater complexity. Especially when the client needs to compute an expiration timestamp
|
|
locally as outlined in the last paragraph in the Proposal section.
|
|
|
|
## Security considerations
|
|
|
|
This does not really have a security implication. The server timestamp is exposed
|
|
to clients but this data is available anyways when combining the
|
|
`unsigned.age` and the `origin_server_ts` of an event.
|