Spracherkennung für: .proto vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]
// ## 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;
}
[Dauer der Verarbeitung: 0.3 Sekunden, vorverarbeitet 2026-04-27]