| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315 |
- // ## Device to Mediator Protocol (Supplementary)
- //
- // This is a supplementary section to the corresponding structbuf section
- // with complementary messages that use protobuf instead of structbuf. All
- // defined messages here follow the same logic.
- //
- // Note that all messages defined here, with the exception of `ClientUrlInfo`,
- // are wrapped by `payload.container`.
- syntax = "proto3";
- package d2m;
- option java_package = "ch.threema.protobuf.d2m";
- // D2M protocol versions.
- enum ProtocolVersion {
- // Initial D2M protocol version (alpha, may break).
- V0 = 0;
- }
- // Send along client information when connecting to the mediator server.
- //
- // This message is serialized, hex-encoded (lowercase) and then used as the
- // WebSocket path.
- //
- // Type: n/a
- // Direction: Client -> Server
- message ClientUrlInfo {
- reserved 2; // Deprecated numeric server group
- // 32 byte device group id (`DGPK.public`)
- bytes device_group_id = 1;
- // Server group, as assigned by the server when the Threema identity has been
- // created. Must consist of only digits or ASCII letters (`^[0-9a-zA-Z]+$`).
- string server_group = 3;
- }
- // Initial message from the server, containing an authentication challenge.
- //
- // Type: 0x10
- // Direction: Client <-- Server
- message ServerHello {
- // Highest protocol version (`ProtocolVersion`) the server supports.
- uint32 version = 1;
- // 32 byte ephemeral server key (`ESK.public`)
- bytes esk = 2;
- // 32 byte random challenge
- bytes challenge = 3;
- }
- // Policy determining the device slot's lifetime.
- enum DeviceSlotExpirationPolicy {
- // The device slot should be removed shortly after the device
- // disconnected. However, there should be a delay of several minutes to
- // ensure that the device can reconnect if it disconnected unintentionally.
- VOLATILE = 0;
- // The device slot should be kept as long as possible
- PERSISTENT = 1;
- }
- // Device registration state on the mediator server.
- enum DeviceSlotState {
- // A new device slot has been allocated for the device (i.e. the device's
- // id was not registered on the server).
- NEW = 0;
- // An existing device slot has been reused for the device (i.e. the
- // device's id is already registered on the server).
- EXISTING = 1;
- }
- // Initial message from the client, containing the authentication challenge
- // response and additional login information.
- //
- // Type: 0x11
- // Direction: Client --> Server
- message ClientHello {
- // Protocol version (`ProtocolVersion`) which the client has selected.
- uint32 version = 1;
- // Challenge response (72 bytes) for authentication.
- //
- // The response is created by encrypting the server's challenge in the
- // following way:
- //
- // ```text
- // XSalsa20-Poly1305(
- // key=X25519HSalsa20(DGPK.secret, ESK.public),
- // nonce=<random>,
- // )
- // ```
- //
- // The nonce is then prefixed to the encrypted challenge.
- bytes response = 2;
- // Unique device id
- fixed64 device_id = 3;
- // Policy to be applied in case the device id is not registered on the server
- // and all device slots have been exhausted.
- enum DeviceSlotsExhaustedPolicy {
- // Terminate the connection
- REJECT = 0;
- // Drop the least recently used device
- DROP_LEAST_RECENT = 1;
- }
- DeviceSlotsExhaustedPolicy device_slots_exhausted_policy = 4;
- // Policy determining the device slot's lifetime
- DeviceSlotExpirationPolicy device_slot_expiration_policy = 5;
- // The expected device slot state on the server.
- //
- // If the expected device slot state does not match the actual device slot
- // state, the device will be dropped by the mediator server with the close
- // code `4115` before being registered.
- DeviceSlotState expected_device_slot_state = 7;
- // Device info (`d2d.DeviceInfo`), encrypted by `DGDIK.secret` and prefixed
- // with a random nonce.
- bytes encrypted_device_info = 6;
- }
- // Parts of the server's configuration and the device slot state.
- //
- // Type: 0x12
- // Direction: Client <-- Server
- message ServerInfo {
- // Current Unix-ish timestamp in milliseconds of the server.
- //
- // If the client's current timestamp deviates by more than 20 minutes, the
- // client should disconnect and prompt the user to synchronise its clock.
- // The user should also have an option to _connect anyway_ which should be
- // cached for a reasonable amount of time.
- uint64 current_time = 4;
- // Maximum number of device slots
- uint32 max_device_slots = 1;
- // Informs the device about its device slot state on the server
- DeviceSlotState device_slot_state = 2;
- // Device data shared among devices (`SharedDeviceData`), encrypted by
- // `DGSDDK.secret` and prefixed with a random nonce.
- bytes encrypted_shared_device_data = 3;
- // Amount of messages in the reflection queue that will now be sent to the
- // device. If the client is up-to-date, the value will be 0.
- //
- // Note: The amount of messages in the reflection queue may increase at any
- // time, so there is no guarantee that `ReflectionQueueDry` will be received
- // after having received `reflection_queue_length` reflected messages.
- uint32 reflection_queue_length = 5;
- }
- // The device's reflection queue on the server has been fully transmitted to
- // the device.
- //
- // Note: This does not mean that reflected messages have already been
- // acknowledged by the device!
- //
- // Type: 0x20
- // Direction: Client <-- Server
- message ReflectionQueueDry {}
- // The device's role has been promoted to leader, indicating that the device
- // should now request to receive and reflect messages from the chat server.
- //
- // Type: 0x21
- // Direction: Client <-- Server
- message RolePromotedToLeader {}
- // Request device information of all devices.
- //
- // Type: 0x30
- // Direction: Client --> Server
- message GetDevicesInfo {}
- // Device information of all devices.
- //
- // Type: 0x31
- // Direction: Client <-- Server
- message DevicesInfo {
- // Device id to (augmented) device info map of all devices.
- message AugmentedDeviceInfo {
- // Device info (`d2d.DeviceInfo`), encrypted by `DGDIK.secret` and prefixed
- // with a random nonce.
- bytes encrypted_device_info = 1;
- // Connection state
- oneof connection_state {
- // Unix-ish timestamp in milliseconds containing the most recent login
- // time of the device. Only set if device is currently connected.
- uint64 connected_since = 2;
- // Unix-ish timestamp in milliseconds containing the most recent
- // disconnect time of the device. Only set if device is not connected.
- uint64 last_disconnect_at = 4;
- }
- // Expiration policy of the device.
- DeviceSlotExpirationPolicy device_slot_expiration_policy = 3;
- }
- map<fixed64, AugmentedDeviceInfo> augmented_device_info = 1;
- }
- // Request to drop a device and free its device slot.
- //
- // Type: 0x32
- // Direction: Client --> Server
- message DropDevice {
- // Unique device id
- fixed64 device_id = 1;
- }
- // Acknowledges that a device has been dropped and the device slot has been
- // free'd.
- //
- // Type: 0x33
- // Direction: Client <-- Server
- message DropDeviceAck {
- // Unique device id
- fixed64 device_id = 1;
- }
- // Set the shared device data which is being sent to each device during login.
- //
- // Type: 0x34
- // Direction: Client --> Server
- message SetSharedDeviceData {
- // Device data shared among devices (`d2d.SharedDeviceData`), encrypted by
- // `DGSDDK.secret` and prefixed with a random nonce.
- bytes encrypted_shared_device_data = 1;
- }
- // Acquires a device group lock for an atomic operation shared across the
- // device group.
- //
- // Reflection messages from the device to the mediator server will only be
- // reflected once the transaction is committed.
- //
- // Type: 0x40
- // Direction: Client --> Server
- message BeginTransaction {
- // The transaction scope (`d2d.TransactionScope`), encrypted by
- // `DGTSK.secret` and prefixed with a random nonce.
- bytes encrypted_scope = 1;
- // Time-to-live in seconds for this transaction. Once the TTL is reached, the
- // mediator server will abort the transaction and disconnect the client. When
- // set to `0`, the server's maximum transaction TTL will be used.
- uint32 ttl = 2;
- }
- // Acknowledges that the device group lock has been acquired and that the
- // transaction has been started.
- //
- // Type: 0x41
- // Direction: Client <-- Server
- message BeginTransactionAck {}
- // Commits a transaction, releases a device group lock.
- //
- // Type: 0x42
- // Direction: Client --> Server
- message CommitTransaction {}
- // Acknowledges that the transaction has been committed and that the device
- // group lock has been released.
- //
- // Type: 0x43
- // Direction: Client <-- Server
- message CommitTransactionAck {}
- // A `BeginTransaction` request is rejected because another transaction is
- // already in process.
- //
- // Type: 0x44
- // Direction: Client <-- Server
- message TransactionRejected {
- // The device that currently holds the lock
- fixed64 device_id = 1;
- // The encrypted transaction scope (`d2d.TransactionScope`) associated with
- // the currently locked transaction, encrypted by `DGTSK.secret` and prefixed
- // with a random nonce.
- bytes encrypted_scope = 2;
- }
- // When a transaction ends (either because it was committed or because the
- // device disconnected), this message is sent to all connected devices except
- // for the device that committed the transaction.
- //
- // This can be used by the other devices as a "retry signal" if a previous
- // "BeginTransaction" attempt was unsuccessful.
- //
- // Type: 0x45
- // Direction: Client <-- Server
- message TransactionEnded {
- // The device that held the lock up until now
- fixed64 device_id = 1;
- // The encrypted transaction scope (`d2d.TransactionScope`) associated with
- // the transaction that just ended, encrypted by `DGTSK.secret` and prefixed
- // with a random nonce.
- bytes encrypted_scope = 2;
- }
|