package groupcall

Mouse Melon logoGet desktop application:
View/edit binary Protocol Buffers messages

message CallState

group-call.proto:423

Current call state as announced by the designated client. Note: The `CallState` accurateness must not be relied upon as it can be out of date and can be replayed by the SFU.

message CallState.Participant

group-call.proto:435

Information for a single participant.

Used in: CallState

message CallState.Participant.Guest

group-call.proto:448

A _guest_ participant.

Used in: Participant

message CallState.Participant.Normal

group-call.proto:439

A _normal_ participant, i.e. a Threema client.

Used in: Participant

message ParticipantToParticipant

group-call.proto:824

Messages sent from one participant to another. Note that these are relayed via `SfuToParticipant.Envelope` and `ParticipantToSfu.Envelope` in order to prevent races with `ParticipantJoined`/`ParticipantLeft`.

(message has no fields)

message ParticipantToParticipant.Admin

group-call.proto:1128

Messages from admins towards participants (including admins).

(message has no fields)

message ParticipantToParticipant.Admin.Envelope

group-call.proto:1142

Message from an administrator, encrypted by: ```text XSalsa20-Poly1305( key=X25519HSalsa20(GCAMK.secret, <receiver.PCK>.public), nonce=<sender.PCCK> || <sender.PCSN+>, ) ``` IMPORTANT: The `ParticipantToParticipant.Envelope` that encapsulates this message shall be encrypted by the same `PCSN` as used for this `Envelope`. The only difference is that the sender uses `GCAMK` instead of its ephemeral `PCK`.

message ParticipantToParticipant.Admin.ForceCaptureStateOff

group-call.proto:1191

Force the receiver's capture device to be turned off. Note: This is a momentary enforcement. A participant may immediately restart capturing a device (e.g. unmute itself) and the message is not repeated towards newly joined participants. When receiving this message: 1. Look up the corresponding device. If none could be found, abort these steps. 2. If the device's capture state is already _off_, abort these steps. 3. Send a `CaptureState` message for the device and follow the creation steps of that message (i.e. stop capturing, etc.).

Used in: Envelope

enum ParticipantToParticipant.Admin.ForceCaptureStateOff.Device

group-call.proto:1192

Used in: ForceCaptureStateOff

message ParticipantToParticipant.Admin.ForceFocus

group-call.proto:1219

Force focus on a specific participant. Note: This is a momentary enforcement. A participant may immediately remove the focus and the message is not repeated towards newly joined participants. When receiving this message: 1. Look up the participant to be focused. If none could be found, abort these steps. 2. Focus the participant in the UI. The camera or screen feed subscription may need to be created (e.g. participant was not visible in the viewport before) or updated (e.g. display resolution changes due to focus) by a corresponding `Subscribe` message sent to the SFU.

Used in: Envelope

message ParticipantToParticipant.Admin.ForceLeave

group-call.proto:1176

Force the receiver to leave the call.

Used in: Envelope

(message has no fields)

message ParticipantToParticipant.Admin.PromoteToAdmin

group-call.proto:1173

Promote the receiver to an administrator. Note: This is final for the scope of this Group Call. An administrator cannot be demoted. When receiving this message: 1. If the user already is an administrator, abort these steps. 2. Derive GCAMK and calculate the associated public key from the received `gcak`. If it does not match the known `GCAMK.public`, log a warning and abort these steps. 3. Send an `Admin.ReportAsAdmin` message to all other participants (including the sender who promoted the user to an admin). 4. Notify the user of its admin status and enable administration functionality in the UI.

Used in: Envelope

message ParticipantToParticipant.Admin.ReportAsAdmin

group-call.proto:1156

Report as an administrator. When receiving this message, mark the sender as an administrator in the UI.

Used in: Envelope

(message has no fields)

message ParticipantToParticipant.CaptureState

group-call.proto:1283

Signals a participant's device capturing state. When creating this message: 1. Let `device` be the device whose state is to be updated. 2. If `device` is to be turned _off_: 1. Stop capturing from the device. 2. Pause the corresponding media track. 3. If `device` is to be turned _on_: 1. Start capturing from the device. 2. Resume the corresponding media track. 4. Send the `CaptureState` message for the `device`. When receiving this message: 1. Let `device` be the device of the sender whose state has been updated. 2. If `device` was turned _off_ and the user is subscribed to the given `device`'s feed: 1. Stop displaying the corresponding media feed in the UI. 2. Pause the corresponding media track. 3. If `device` is `Microphone`, no further action is necessary. 4. If `device` is `Camera`, send a `ParticipantCamera.Unsubcribe` message to the SFU. 5. If `device` is `Screen`, send a `ParticipantScreen.Unsubcribe` message to the SFU. 3. If `device` was turned _on_ and the user is not subscribed to the given `device`'s feed: 1. Resume the corresponding media track. 2. Start displaying the corresponding media feed in the UI. 3. If `device` is `Microphone`, no further action is necessary. 4. If `device` is `Camera`, send a `ParticipantCamera.Subscribe` message to the SFU. 5. If `device` is `Screen`, send a `ParticipantScreen.Subscribe` message to the SFU.

Used in: Envelope

message ParticipantToParticipant.CaptureState.Camera

group-call.proto:1293

Capture state of the camera.

Used in: CaptureState

message ParticipantToParticipant.CaptureState.Microphone

group-call.proto:1285

Capture state of the microphone.

Used in: CaptureState

message ParticipantToParticipant.CaptureState.Screen

group-call.proto:1301

Capture state of the screen.

message ParticipantToParticipant.Envelope

group-call.proto:1108

After fulfilling either the (normal) handshake or the guest handshake, all following messages are encoded in `Envelope` and encrypted by: ```text XSalsa20-Poly1305( key=X25519HSalsa20(<sender.PCK>.secret, <receiver.PCK>.public), nonce=<sender.PCCK> || <sender.PCSN+>, ) ``` Note: Since the guest handshake is TOFU, an attacker knowing `GCK` having control over the SFU may apply a MITM attack between a guest participant and another participant. The attacker would be able to silently eavesdrop all media traffic between the two participants. This is repeatable for all other participants and means the attacker is able to silently eavesdrop the whole call. Therefore, if a call is not open for guests, `GuestHello` (and `GuestAuth`) **must not** be accepted. When receiving this message: 1. If the participant's _handshake state_ is not `done`, log a warning and abort these steps. 2. Handle the message according to the content.

message ParticipantToParticipant.Handshake

group-call.proto:854

Messages required for the initial lock-step handshake between participants.

(message has no fields)

message ParticipantToParticipant.Handshake.Auth

group-call.proto:988

Second and final handshake message. When receiving this message: 1. If the participant's _handshake state_ is not `await-auth`, log a warning and abort these steps. 2. If the repeated `pck` does not equal the local `PCK.public` used towards this participant, log a warning and abort these steps. 3. If the repeated `pcck` does not equal the local `PCCK` used towards this participant, log a warning and abort these steps. 4. Set the participant's _handshake state_ to `done`.

Used in: AuthEnvelope

message ParticipantToParticipant.Handshake.AuthEnvelope

group-call.proto:913

If both sides started the normal handshake, the second message is encrypted in the following way: 1. Let `inner-nonce` be a random nonce. 2. Let `inner-data` be encrypted by: ```text S = X25519HSalsa20(<sender.CK>.secret, <receiver.CK>.public) GCNHAK = Blake2b( key=S, salt='nha', personal='3ma-call', input=GCKH) XSalsa20-Poly1305( key=GCNHAK, nonce=<inner-nonce>, data=<AuthEnvelope(Auth)>, ) ``` 3. Let `outer-data` be encrypted by: ```text XSalsa20-Poly1305( key=X25519HSalsa20(<sender.PCK>.secret, <receiver.PCK>.public), nonce=<sender.PCCK> || <sender.PCSN+>, data=<inner-nonce> || <inner-data>, ) ``` 4. Return `outer-data`. If either side started the guest handshake, the second message is encrypted by: ```text XSalsa20-Poly1305( key=X25519HSalsa20(<sender.PCK>.secret, <receiver.PCK>.public), nonce=<sender.PCCK> || <sender.PCSN+>, data=<AuthEnvelope(GuestAuth)>, ) ``` When receiving this message: 1. If either side initiated a guest handshake via a `GuestHello`, expect `guest_auth` to be set. If `guest_auth` is not set, log a warning and abort these steps. 2. If both sides initiated the (normal) handshake, expect `auth` to be set. If `auth` is not set, log a warning and abort these steps.

message ParticipantToParticipant.Handshake.GuestAuth

group-call.proto:1063

Second and final handshake message triggered if either side initiated the guest handshake. When receiving this message: 1. If the participant's _handshake state_ is not `await-guest-auth`, log a warning and abort these steps. 2. If the repeated `pck` does not equal the local `PCK.public` used towards this participant, log a warning and abort these steps. 3. If the repeated `pcck` does not equal the local `PCCK` used towards this participant, log a warning and abort these steps. 4. Set the participant's _handshake state_ to `done`.

Used in: AuthEnvelope

message ParticipantToParticipant.Handshake.GuestHello

group-call.proto:1036

Initial guest handshake message. When creating this message as a newly joined guest participant towards another participant: 1. Set the participant's _handshake state_ to `await-ep-hello`. 2. Send this message. When receiving this message: 1. If guest participants are not allowed for this call, log a warning and abort these steps. 2. (Placeholder for conference call PCK != GCAMK step.) 3. If the sender is a newly joined participant and therefore the _handshake state_ was set to `await-np-hello` (as described by the _Join/Leave_ section): 1. Respond by sending a `GuestHello` message, immediately followed by a `GuestAuth` message. 2. Set the participant's _handshake state_ to `await-guest-auth` and abort these steps. 4. If the participant's _handshake state_ is `await-ep-hello`: 1. If the `pck` reflects the local PCK.public or the `pcck` reflects the local PCCK, log a warning and abort these steps. 2. Respond by sending a `GuestAuth` message. 3. Set the participant's _handshake state_ to `await-guest-auth` and abort these steps. 5. Log a warning and abort these steps.

Used in: HelloEnvelope

message ParticipantToParticipant.Handshake.Hello

group-call.proto:959

Initial handshake message. When creating this message as a newly joined participant towards another participant: 1. Set the participant's _handshake state_ to `await-ep-hello`. 2. Send this message. When receiving this message as a guest participant: 1. Map it to a `GuestHello` in the following way: - `name`: `Hello.nickname` - `pck`: `Hello.pck` - `pcck`: `Hello.pcck` 2. Handle the mapped `GuestHello` as if it had been received directly. When receiving this message as a regular participant: 1. (Placeholder for conference call PCK != GCAMK step.) 2. If the group call is scoped to a (Threema) group and `identity` is not part of the associated group (including the user itself), log a warning and abort these steps. 3. If the sender is a newly joined participant and therefore the _handshake state_ was set to `await-np-hello` (as described by the _Join/Leave_ section): 1. Respond by sending a `Hello` message, immediately followed by an `Auth` message. 2. Set the participant's _handshake state_ to `await-auth` and abort these steps. 4. If the participant's _handshake state_ is `await-ep-hello`: 1. If the `pck` reflects the local PCK.public or the `pcck` reflects the local PCCK, log a warning and abort these steps. 2. Respond by sending an `Auth` message. 3. Set the participant's _handshake state_ to `await-auth` and abort these steps. 5. Log a warning and abort these steps.

Used in: HelloEnvelope

message ParticipantToParticipant.Handshake.HelloEnvelope

group-call.proto:858

The first message (`HelloEnvelope(Hello)` or `HelloEnvelope(GuestHello)`) of both sides is always encrypted by `GCHK`, prefixed with a random nonce.

message ParticipantToParticipant.HoldState

group-call.proto:1330

Signals that a participant is currently on hold / temporarily away. When creating this message: 1. Send a `CaptureState` message for each capture device. Follow the creation steps of that message. 2. Send the `HoldState` message. When receiving this message: 1. Apply the _hold_ state in the UI for the participant. 2. Pause any video-based media tracks of the participant. 3. If subscribed to the participant's camera feed, send a `ParticipantCamera.Unsubcribe` message to the SFU. 4. If subscribed to the participant's screen feed, send a `ParticipantScreen.Unsubcribe` message to the SFU.

Used in: Envelope

(message has no fields)

message ParticipantToParticipant.MediaKey

group-call.proto:1226

Media keys a participant will use for sending. Will be sent towards new and existing participants as described by the _Join/Leave_ section.

Used in: Envelope, Handshake.Auth, Handshake.GuestAuth

message ParticipantToParticipant.OuterEnvelope

group-call.proto:839

Used for all messages that are relayed from one participant to another via the SFU. When receiving a relayed message: 1. If the `receiver` is not the user's assigned participant id, discard the message and abort these steps. 2. If the `sender` is unknown, discard the message and abort these steps. 3. Decrypt `encrypted_data` according to the current _handshake state_ and handle the inner envelope: - `await-ep-hello` or `await-np-hello`: Expect a `Handshake.HelloEnvelope`. - `await-auth`: Expect a `Handshake.AuthEnvelope`. - `done`: Expect a post-auth `Envelope`.

Used in: ParticipantToSfu.Envelope, SfuToParticipant.Envelope

message ParticipantToSfu

group-call.proto:698

Messages sent from a participant to the SFU via a data channel. Data Channel Parameters: - `ordered`: `true` - `negotiated`: `true` - `id`: `0`

(message has no fields)

message ParticipantToSfu.Envelope

group-call.proto:707

The enveloped message towards the SFU. When relaying a message from one participant to another, omit any additional padding. IMPORTANT: The format of the `SfuToParticipant.Envelope` and `ParticipantToSfu.Envelope` must be compatible for the relay case, so the SFU can forward the data without having to re-encode.

message ParticipantToSfu.ParticipantCamera

group-call.proto:774

Subscribe or unsubscribe to a participant's camera feed. When receiving this message: 1. If the `participant_id` refers to the sender's participant ID or an unknown participant ID, discard the message and abort these steps. 2. If `subscribe` is set, forward the camera feed to the client that fits best to the provided parameters. 3. If `unsubscribe` is set, stop forwarding camera feed of this participant to the client.

Used in: Envelope

message ParticipantToSfu.ParticipantCamera.Subscribe

group-call.proto:780

Subscribe to a participant's camera feed.

Used in: ParticipantCamera

message ParticipantToSfu.ParticipantCamera.Unsubscribe

group-call.proto:792

Unsubscribe a participant's camera feed.

Used in: ParticipantCamera

(message has no fields)

message ParticipantToSfu.ParticipantMicrophone

group-call.proto:747

Subscribe or unsubscribe to a participant's microphone feed. When receiving this message: 1. If the `participant_id` refers to the sender's participant ID or an unknown participant ID, discard the message and abort these steps. 2. If `subscribe` is set, forward the microphone feed to the client that fits best to the provided parameters. 3. If `unsubscribe` is set, stop forwarding microphone feed of this participant to the client.

Used in: Envelope

message ParticipantToSfu.ParticipantMicrophone.Subscribe

group-call.proto:753

Subscribe to a participant's microphone feed.

Used in: ParticipantMicrophone

(message has no fields)

message ParticipantToSfu.ParticipantMicrophone.Unsubscribe

group-call.proto:756

Unsubscribe a participant's microphone feed.

Used in: ParticipantMicrophone

(message has no fields)

message ParticipantToSfu.ParticipantScreen

group-call.proto:801

Subscribe or unsubscribe to a participant's screen feed.

Used in: Envelope

message ParticipantToSfu.ParticipantScreen.Subscribe

group-call.proto:807

Subscribe to a participant's screen feed.

Used in: ParticipantScreen

(message has no fields)

message ParticipantToSfu.ParticipantScreen.Unsubscribe

group-call.proto:810

Unsubscribe a participant's screen feed.

Used in: ParticipantScreen

(message has no fields)

message ParticipantToSfu.UpdateCallState

group-call.proto:731

Update the call state that can be retrieved via a _peek_. Note: Only the currently designated client should send this to the SFU. When receiving this message: 1. Store the encrypted call state and make it accessible via _peek_ HTTP requests. 2. Start a timer to purge the call state after 30s. Subsequent `UpdateCallState` messages will update the call state and reset the timer.

Used in: Envelope

message SfuHttpRequest

group-call.proto:465

Request payloads sent to the SFU as part of an HTTP request.

(message has no fields)

message SfuHttpRequest.Join

group-call.proto:533

Requests to join the group call with the given Group Call ID. The URL is formed in the following way: <sfu_base_url>/v1/join/<call_id-as-hex> When sending this request: 1. Use `POST` as method. 2. Set the `Authorization` header to `ThreemaSfuToken <sfu-token>`. 3. Set the encoded `SfuHttpRequest.Join` message as body. When receiving this request: 1. If the `Authorization` header is missing, the provided `sfu-token` in the `Authorization` header is invalid or expired, respond with status code `401` and abort these steps. 2. If the provided data is invalid, respond with status code `400` and abort these steps. 3. If `call_id` does not equal the Call ID from the URL (decoded `call_id-as-hex`), respond with status code `400` and abort these steps. 4. If the `protocol_version` is unsupported by the SFU, respond with status code `419` and abort these steps. 5. If no more participants can join the group call for the given `call_id`, respond with status code `503` and abort these steps. 6. Respond with status code `200` and an encoded `SfuHttpResponse.Join` message as body. 7. Once the WebRTC connection has been established, announce the newly joined participant to all other participants via the corresponding data channel. If no WebRTC connection is being established within 30s, the participant ID is no longer reserved for the client and the group call must be teared down if no other participant started joining this group call.

message SfuHttpRequest.Peek

group-call.proto:495

Peeks for the current state of the group call for the given Group Call ID. IMPORTANT: The _peek_ process is considered stable across different protocol versions. Therefore, the message **should** maintain backwards compatibility! The URL is formed in the following way: <sfu_base_url>/v1/peek/<call_id-as-hex> When sending this request: 1. Use `POST` as method. 2. Set the `Authorization` header to `ThreemaSfuToken <sfu-token>`. 3. Set the encoded `SfuHttpRequest.Peek` message as body. When receiving this request: 1. If the `Authorization` header is missing, the provided `sfu-token` in the `Authorization` header is invalid or expired, respond with status code `401` and abort these steps. 2. If the provided data is invalid, respond with status code `400` and abort these steps. 3. If `call_id` does not equal the Call ID from the URL (decoded `call_id-as-hex`), respond with status code `400` and abort these steps. 4. If no group call for the given `call_id` is currently running, respond with status code `404` and abort these steps. 5. Respond with status code `200` and an encoded `SfuHttpResponse.Peek` message as body.

message SfuHttpResponse

group-call.proto:549

Response payloads sent back from the SFU as part of an HTTP request.

(message has no fields)

message SfuHttpResponse.Join

group-call.proto:583

Information returned when joining a group call. When receiving this response, initiate the WebRTC connection to the SFU and consider the connection established when the `SfuToParticipant.Hello` message has been received on the associated data channel.

message SfuHttpResponse.Join.Address

group-call.proto:598

Address the SFU is listening for a WebRTC connection.

Used in: Join

enum SfuHttpResponse.Join.Address.Protocol

group-call.proto:600

Protocol.

Used in: Address

message SfuHttpResponse.Peek

group-call.proto:558

Information returned for a running group call. IMPORTANT: The _peek_ process is considered stable across different protocol versions. Therefore, the message **should** maintain backwards compatibility! Note: The included `CallState` information may not be accurate and should not be relied upon.

message SfuToParticipant

group-call.proto:636

Messages sent from the SFU to a participant via a data channel. Data Channel Parameters: - `ordered`: `true` - `negotiated`: `true` - `id`: `0`

(message has no fields)

message SfuToParticipant.Envelope

group-call.proto:645

The enveloped message from the SFU. When relaying a message from one participant to another, omit any additional padding. IMPORTANT: The format of the `SfuToParticipant.Envelope` and `ParticipantToSfu.Envelope` must be compatible for the relay case, so the SFU can forward the data without having to re-encode.

message SfuToParticipant.Hello

group-call.proto:665

Announces all other participants to a newly joined participant. When receiving this message: 1. If a `Hello` was received before (i.e. if the receiver is not a newly joined participant), log a warning and abort these steps. 2. Initiate the participant to participate handshake for each participant listed in this message.

Used in: Envelope

message SfuToParticipant.ParticipantJoined

group-call.proto:678

Announces that a new participant joined to existing participants. When receiving this message: 1. Look up the participant. If it already exists (i.e. never _left_), log a warning and abort these steps. 2. Run the corresponding steps described by the _Join/Leave_ section.

Used in: Envelope

message SfuToParticipant.ParticipantLeft

group-call.proto:688

Announces that a participant left to existing participants. When receiving this message: 1. Look up the participant. If it was never announced to have _joined_ by an associated `ParticipantJoined` message, log a warning and abort these steps. 2. Run the corresponding steps described by the _Join/Leave_ section.

Used in: Envelope