pub enum RoomMessage {
Show 19 variants
MemberAnnounce {
sender_fingerprint: String,
wrapped_session_key: Option<String>,
display_name: Option<String>,
sender_ed25519_pubkey: Option<String>,
},
SessionKeyRequest {
requester_fingerprint: String,
},
Encrypted {
sender_fingerprint: String,
session_id: String,
ciphertext_b64: String,
},
Plain {
sender_fingerprint: String,
body: String,
},
MemberLeave {
sender_fingerprint: String,
},
RotateRoomKey {
rotator_fingerprint: String,
new_salt: Vec<u8>,
},
Typing {
sender_fingerprint: String,
},
FileOffer {
sender_fingerprint: String,
file_id: String,
name: String,
size_bytes: u64,
mime: Option<String>,
chunk_count: u32,
encrypted_meta: Option<EncryptedFileMeta>,
},
FileChunk {
sender_fingerprint: String,
file_id: String,
chunk_index: u32,
total_chunks: u32,
data_b64: String,
},
OwnerGrant {
room_id: String,
target_fingerprint: String,
},
BanMember {
room_id: String,
target_fingerprint: String,
},
SasInit {
tx_id: String,
ephemeral_x25519_pubkey_b64: String,
target_fingerprint: String,
},
SasResponse {
tx_id: String,
ephemeral_x25519_pubkey_b64: String,
},
SasConfirm {
tx_id: String,
matched: bool,
},
JoinRefused {
room_id: String,
target_fingerprint: String,
reason: String,
},
CodeJoinRequest {
room_id: String,
joiner_x25519_pubkey_b64: String,
code: String,
},
CodeJoinResponse {
room_id: String,
target_fingerprint: String,
owner_x25519_pubkey_b64: String,
owner_session_id: String,
wrapped_session_key_b64: String,
nonce_b64: String,
},
ProfileUpdate {
sender_fingerprint: String,
username: Option<String>,
updated_at: i64,
},
ContactRequest {
requester_fingerprint: String,
display_name: Option<String>,
note: Option<String>,
sender_ed25519_pubkey: Option<String>,
},
}Expand description
All messages on a room’s per-room topic.
Variants§
MemberAnnounce
Announce my presence in the room. For encrypted rooms, also share my Megolm session key (passphrase-wrapped).
Fields
wrapped_session_key: Option<String>base64(nonce || chacha20poly1305_ciphertext) of the Megolm SessionKey, encrypted under the passphrase-derived key. None for unencrypted rooms.
display_name: Option<String>Optional human-readable display name. Serde defaults to
None for forward compat with older peers.
sender_ed25519_pubkey: Option<String>Base64 of the sender’s 32-byte Ed25519 public key. Lets every
existing member learn the new member’s pubkey on first contact,
so they can verify future SignedRoomMessage envelopes from
this fingerprint. #[serde(default)] for forward compat: a
pre-0.3.0 peer that doesn’t send this still works, but its
signed messages can’t be verified until it re-announces.
SessionKeyRequest
A request from a recently-joined member: “I need session keys”. Existing members respond with MemberAnnounce.
Encrypted
An encrypted message in an encrypted room.
Fields
Plain
A plaintext message in an unencrypted room.
MemberLeave
Explicit leave notification.
RotateRoomKey
“I’m rotating the room key — derive a new passphrase key from
new_salt + the new passphrase you’ll be told out-of-band, then
wait for my MemberAnnounce.” Phase 3 v1: simplistic — only the
rotator’s outbound changes; receivers must opt in by entering
the new passphrase to decrypt new wrapped session keys.
Fields
Typing
Ephemeral “I’m typing” signal. TTL on the receive side is 3s.
FileOffer
Announce a file the sender is about to push. The receiver creates
an attachment row (status=offered) and waits for chunks. For
encrypted rooms encrypted_meta carries the Megolm-wrapped file
key + ChaCha20 nonce.
Fields
encrypted_meta: Option<EncryptedFileMeta>FileChunk
One chunk of an in-flight file. Receivers reassemble by index
and verify the final SHA-256 against file_id.
Fields
OwnerGrant
Phase B: an existing owner promotes target_fingerprint to
owner. MUST be sent inside WireMessage::Signed — the signer
must be on the room’s current owner_fingerprints list for
honest receivers to apply the change.
BanMember
Phase B: an existing owner bans target_fingerprint from the
room. MUST be sent inside WireMessage::Signed. Honest clients
then ignore the banned fingerprint’s MemberAnnounce + messages.
The cryptographic enforcement is the immediate RotateRoomKey
that the banning owner sends right after.
SasInit
Phase G: SAS verification step 1. The initiator picks a random
tx_id and an ephemeral X25519 keypair, sends the pubkey.
MUST be sent inside WireMessage::Signed so the receiver can
bind this ephemeral key to the initiator’s Ed25519 identity.
SasResponse
Phase G: SAS step 2 — responder’s ephemeral X25519 pubkey. Both sides now have what they need to compute the shared secret and derive the SAS code locally. Signed.
SasConfirm
Phase G: SAS step 3 — once both sides have OOB-compared the
derived code and pressed “Match”, each broadcasts this. On
receiving the partner’s matched=true, the local side flips
verified=1 for the partner’s fingerprint. Signed.
JoinRefused
Phase E: an existing owner of a verified_only room is
telling target_fingerprint (an unverified joiner) why their
announce went unanswered. Replaces a silent hang on the
joiner’s side. Signed.
CodeJoinRequest
Phase F: a joiner is asking to enter a room using a short-lived owner-issued code (no passphrase). Includes the joiner’s ephemeral X25519 pubkey for ECDH key delivery. Signed (so the owner knows who’s asking).
CodeJoinResponse
Phase F: an issuing owner’s response to a valid CodeJoinRequest.
Carries the owner’s ephemeral X25519 pubkey + the current Megolm
session key wrapped under the ECDH-derived key. Joiner does
X25519 the other direction, derives the same wrap key, unwraps
the session key. Signed.
Fields
ProfileUpdate
Phase 0.5: a peer is announcing (or clearing) their self-declared
username. MUST be sent inside WireMessage::Signed — receivers
require verified_signer == sender_fingerprint. Last-write-wins
by updated_at (monotonic ms). username = None clears the
previously-set username and the peer renders as [anonymous].
ContactRequest
huddle 1.0: a contact/DM request delivered to the target’s relay
inbox (inbox_room_id). MUST be sent inside WireMessage::Signed —
the signer’s fingerprint IS the requester’s identity (the whole
point: it proves who’s asking). Carries the requester’s Ed25519
pubkey so the recipient can TOFU-pin it and later derive the DM ECDH
key without a round-trip.
Trait Implementations§
Source§impl Clone for RoomMessage
impl Clone for RoomMessage
Source§fn clone(&self) -> RoomMessage
fn clone(&self) -> RoomMessage
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for RoomMessage
impl Debug for RoomMessage
Source§impl<'de> Deserialize<'de> for RoomMessage
impl<'de> Deserialize<'de> for RoomMessage
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Auto Trait Implementations§
impl Freeze for RoomMessage
impl RefUnwindSafe for RoomMessage
impl Send for RoomMessage
impl Sync for RoomMessage
impl Unpin for RoomMessage
impl UnsafeUnpin for RoomMessage
impl UnwindSafe for RoomMessage
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more