feat(lib): send and receive private messages

Wire private messaging through the client:

- MessageFactory::build_message_user (code 22) and build_message_acked
  (code 23);
- the incoming MessageUser handler now acknowledges freshly delivered
  messages and forwards them to the client instead of only logging them;
- ClientContext buffers received UserMessages;
- Client::send_private_message and Client::take_private_messages expose the
  feature, and UserMessage (with accessors) is re-exported from the crate.

Verified end to end against soulfind: a_private_message_is_delivered_between_users
logs in two clients and asserts one receives the other's message.
This commit is contained in:
michel
2026-07-19 13:31:30 +02:00
parent f61e02e05c
commit a7372cc88e
6 changed files with 195 additions and 3 deletions
+47
View File
@@ -102,6 +102,37 @@ impl UserMessage {
self.message
);
}
/// The server-assigned id of this message (used to acknowledge it).
#[must_use]
pub const fn id(&self) -> u32 {
self.id
}
/// Unix timestamp the server recorded for this message.
#[must_use]
pub const fn timestamp(&self) -> u32 {
self.timestamp
}
/// The username of the sender.
#[must_use]
pub fn username(&self) -> &str {
&self.username
}
/// The message body.
#[must_use]
pub fn message(&self) -> &str {
&self.message
}
/// Whether the server flagged this as freshly delivered (as opposed to a
/// message replayed because it was queued while the recipient was offline).
#[must_use]
pub const fn is_new(&self) -> bool {
self.new_message
}
}
#[derive(Debug, Clone)]
@@ -129,6 +160,7 @@ pub enum ServerMessage {
obfuscation_type: u32,
obfuscated_port: u16,
},
PrivateMessageReceived(UserMessage),
}
pub struct ServerActor {
@@ -418,6 +450,21 @@ impl ServerActor {
);
}
}
ServerMessage::PrivateMessageReceived(user_message) => {
debug!(
"[server] Private message from {}",
user_message.username()
);
if let Err(e) = self
.client_channel
.send(ClientOperation::PrivateMessageReceived(user_message))
{
error!(
"[server] Error forwarding private message to client: {}",
e
);
}
}
ServerMessage::ProcessRead => {
self.process_read();
}