TLS 1.3, channel persistence, membership signaling
- TLS 1.3 on TCP (rustls + tokio-rustls, optional self-signed cert) - Server-side channel CRUD with SQLite persistence - Gateway → voice-node membership bridge via broadcast channel
This commit is contained in:
parent
523680e05d
commit
5534cd01f7
37 changed files with 771 additions and 160 deletions
|
|
@ -1,5 +1,5 @@
|
|||
use anyhow::Result;
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
use tracing::{info, warn};
|
||||
|
||||
use crate::{
|
||||
|
|
@ -17,7 +17,7 @@ use crate::{
|
|||
/// Handle a ChannelCreate request — register a new channel in the store and
|
||||
/// broadcast the new ChannelState to all sessions so their sidebars update.
|
||||
pub async fn handle_channel_create(
|
||||
stream: &mut TcpStream,
|
||||
stream: &mut (impl AsyncRead + AsyncWrite + Unpin),
|
||||
seq: &mut u32,
|
||||
session_id: &str,
|
||||
payload: &[u8],
|
||||
|
|
@ -97,6 +97,17 @@ pub async fn handle_channel_create(
|
|||
|
||||
let created = channels::create(&state.channels, &channel_id, &channel_name, kind.clone()).await;
|
||||
|
||||
// Persist to DB (best-effort, log and continue on failure).
|
||||
if created {
|
||||
if let Err(e) = state
|
||||
.storage
|
||||
.create_channel(&channel_id, &channel_name, kind.as_str())
|
||||
.await
|
||||
{
|
||||
warn!("failed to persist channel to storage: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
if !created {
|
||||
io::send_encrypted(
|
||||
stream,
|
||||
|
|
@ -160,7 +171,7 @@ pub async fn handle_channel_create(
|
|||
/// Handle a ChannelDelete request — remove the channel from the store and
|
||||
/// broadcast the deletion to all sessions.
|
||||
pub async fn handle_channel_delete(
|
||||
stream: &mut TcpStream,
|
||||
stream: &mut (impl AsyncRead + AsyncWrite + Unpin),
|
||||
seq: &mut u32,
|
||||
session_id: &str,
|
||||
payload: &[u8],
|
||||
|
|
@ -190,6 +201,14 @@ pub async fn handle_channel_delete(
|
|||
}
|
||||
|
||||
let existed = channels::delete(&state.channels, &req.channel_id).await;
|
||||
|
||||
// Remove from DB (best-effort).
|
||||
if existed {
|
||||
if let Err(e) = state.storage.delete_channel(&req.channel_id).await {
|
||||
warn!("failed to remove channel from storage: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
if !existed {
|
||||
io::send_encrypted(
|
||||
stream,
|
||||
|
|
@ -229,7 +248,7 @@ pub async fn handle_channel_delete(
|
|||
|
||||
/// Handle a ChannelList request — reply with all known channels.
|
||||
pub async fn handle_channel_list(
|
||||
stream: &mut TcpStream,
|
||||
stream: &mut (impl AsyncRead + AsyncWrite + Unpin),
|
||||
seq: &mut u32,
|
||||
session_id: &str,
|
||||
crypto: &SessionCrypto,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use anyhow::Result;
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
use tracing::info;
|
||||
|
||||
use crate::{
|
||||
|
|
@ -19,7 +19,7 @@ use super::{broadcast_leave, set_channel};
|
|||
const HISTORY_LIMIT: i64 = 50;
|
||||
|
||||
pub async fn join(
|
||||
stream: &mut TcpStream,
|
||||
stream: &mut (impl AsyncRead + AsyncWrite + Unpin),
|
||||
seq: &mut u32,
|
||||
session_id: &str,
|
||||
channel_id: &str,
|
||||
|
|
@ -110,6 +110,18 @@ pub async fn join(
|
|||
});
|
||||
}
|
||||
|
||||
if let Some(tx) = &state.voice_member_tx {
|
||||
if let Some(sess) = session::get(&state.sessions, session_id).await {
|
||||
let event = serde_json::json!({
|
||||
"type": "joined",
|
||||
"channel_id": channel_id,
|
||||
"session_id": session_id,
|
||||
"user_id": sess.user_id,
|
||||
});
|
||||
let _ = tx.send(event.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
info!("session {} joined {channel_id}", &session_id[..8]);
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,22 +1,39 @@
|
|||
use anyhow::Result;
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
use tracing::info;
|
||||
|
||||
use crate::{domain::channels, net::state::State, proto::SessionCrypto};
|
||||
use crate::{domain::{channels, session}, net::state::State, proto::SessionCrypto};
|
||||
|
||||
use super::{broadcast_leave, set_channel};
|
||||
|
||||
pub async fn leave(
|
||||
_stream: &mut TcpStream,
|
||||
_stream: &mut (impl AsyncRead + AsyncWrite + Unpin),
|
||||
_seq: &mut u32,
|
||||
session_id: &str,
|
||||
channel_id: &str,
|
||||
_crypto: &SessionCrypto,
|
||||
state: &State,
|
||||
) -> Result<()> {
|
||||
let user_id = session::get(&state.sessions, session_id)
|
||||
.await
|
||||
.map(|s| s.user_id);
|
||||
|
||||
channels::leave(&state.channels, channel_id, session_id).await;
|
||||
set_channel(state, session_id, None).await;
|
||||
broadcast_leave(state, channel_id, session_id).await;
|
||||
|
||||
if let Some(tx) = &state.voice_member_tx {
|
||||
if let Some(ref uid) = user_id {
|
||||
let event = serde_json::json!({
|
||||
"type": "left",
|
||||
"channel_id": channel_id,
|
||||
"session_id": session_id,
|
||||
"user_id": uid,
|
||||
});
|
||||
let _ = tx.send(event.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
info!("session {} left {channel_id}", &session_id[..8]);
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use anyhow::Result;
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
|
||||
use crate::{
|
||||
domain::session,
|
||||
|
|
@ -14,7 +14,7 @@ use crate::{
|
|||
};
|
||||
|
||||
pub async fn handle_presence_update(
|
||||
_stream: &mut TcpStream,
|
||||
_stream: &mut (impl AsyncRead + AsyncWrite + Unpin),
|
||||
seq: &mut u32,
|
||||
session_id: &str,
|
||||
payload: &[u8],
|
||||
|
|
@ -60,7 +60,7 @@ pub async fn handle_presence_update(
|
|||
}
|
||||
|
||||
pub async fn handle_presence_sync(
|
||||
stream: &mut TcpStream,
|
||||
stream: &mut (impl AsyncRead + AsyncWrite + Unpin),
|
||||
seq: &mut u32,
|
||||
session_id: &str,
|
||||
crypto: &SessionCrypto,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use crate::{
|
|||
};
|
||||
|
||||
pub async fn handle_read_receipt(
|
||||
_stream: &mut tokio::net::TcpStream,
|
||||
_stream: &mut (impl tokio::io::AsyncRead + tokio::io::AsyncWrite + Unpin),
|
||||
seq: &mut u32,
|
||||
session_id: &str,
|
||||
payload: &[u8],
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use anyhow::Result;
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
|
||||
use crate::{
|
||||
domain::session,
|
||||
|
|
@ -8,7 +8,7 @@ use crate::{
|
|||
};
|
||||
|
||||
pub async fn deliver_encrypted(
|
||||
stream: &mut TcpStream,
|
||||
stream: &mut (impl AsyncRead + AsyncWrite + Unpin),
|
||||
seq: &mut u32,
|
||||
session_id: &str,
|
||||
msg: &BroadcastMsg,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use anyhow::Result;
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
|
||||
use crate::{
|
||||
domain::session,
|
||||
|
|
@ -8,7 +8,7 @@ use crate::{
|
|||
};
|
||||
|
||||
pub async fn handle_dm_history(
|
||||
stream: &mut TcpStream,
|
||||
stream: &mut (impl AsyncRead + AsyncWrite + Unpin),
|
||||
seq: &mut u32,
|
||||
session_id: &str,
|
||||
payload: &[u8],
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use anyhow::Result;
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
use tracing::warn;
|
||||
|
||||
use crate::{
|
||||
|
|
@ -14,7 +14,7 @@ use crate::{
|
|||
};
|
||||
|
||||
pub async fn handle_dm_message(
|
||||
stream: &mut TcpStream,
|
||||
stream: &mut (impl AsyncRead + AsyncWrite + Unpin),
|
||||
seq: &mut u32,
|
||||
session_id: &str,
|
||||
payload: &[u8],
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use anyhow::Result;
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
|
||||
use crate::{
|
||||
domain::session,
|
||||
|
|
@ -8,7 +8,7 @@ use crate::{
|
|||
};
|
||||
|
||||
pub async fn handle_dm_start(
|
||||
stream: &mut TcpStream,
|
||||
stream: &mut (impl AsyncRead + AsyncWrite + Unpin),
|
||||
seq: &mut u32,
|
||||
session_id: &str,
|
||||
payload: &[u8],
|
||||
|
|
@ -88,7 +88,7 @@ pub async fn handle_dm_start(
|
|||
}
|
||||
|
||||
pub async fn handle_dm_read_ack(
|
||||
stream: &mut TcpStream,
|
||||
stream: &mut (impl AsyncRead + AsyncWrite + Unpin),
|
||||
seq: &mut u32,
|
||||
session_id: &str,
|
||||
payload: &[u8],
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use anyhow::Result;
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
use tracing::debug;
|
||||
|
||||
use crate::{
|
||||
|
|
@ -11,174 +12,402 @@ use crate::{
|
|||
|
||||
use super::{Ctx, channel, content, direct_message, friends, guild};
|
||||
|
||||
pub async fn dispatch(
|
||||
ctx: &mut Ctx<'_>,
|
||||
pub async fn dispatch<S: AsyncRead + AsyncWrite + Unpin>(
|
||||
ctx: &mut Ctx<'_, S>,
|
||||
session_id: &str,
|
||||
pid: PacketId,
|
||||
payload: &[u8],
|
||||
addr: std::net::SocketAddr,
|
||||
) -> Result<()> {
|
||||
let Ctx {
|
||||
stream,
|
||||
seq,
|
||||
crypto,
|
||||
state,
|
||||
} = ctx;
|
||||
match pid {
|
||||
PacketId::Ping => {
|
||||
let ping: PingPayload = serde_json::from_slice(payload)?;
|
||||
io::send_encrypted(
|
||||
stream,
|
||||
ctx.stream,
|
||||
PacketId::Pong,
|
||||
seq,
|
||||
ctx.seq,
|
||||
&to_payload(&PongPayload {
|
||||
timestamp: ping.timestamp,
|
||||
}),
|
||||
crypto,
|
||||
ctx.crypto,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
PacketId::JoinChannel => {
|
||||
let m: JoinChannelPayload = serde_json::from_slice(payload)?;
|
||||
channel::join(stream, seq, session_id, &m.channel_id, crypto, state).await?;
|
||||
channel::join(ctx.stream, ctx.seq, session_id, &m.channel_id, ctx.crypto, ctx.state)
|
||||
.await?;
|
||||
}
|
||||
PacketId::LeaveChannel => {
|
||||
let m: LeaveChannelPayload = serde_json::from_slice(payload)?;
|
||||
channel::leave(stream, seq, session_id, &m.channel_id, crypto, state).await?;
|
||||
channel::leave(ctx.stream, ctx.seq, session_id, &m.channel_id, ctx.crypto, ctx.state)
|
||||
.await?;
|
||||
}
|
||||
PacketId::ChannelCreate => {
|
||||
channel::handle_channel_create(stream, seq, session_id, payload, crypto, state).await?;
|
||||
channel::handle_channel_create(
|
||||
ctx.stream,
|
||||
ctx.seq,
|
||||
session_id,
|
||||
payload,
|
||||
ctx.crypto,
|
||||
ctx.state,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
PacketId::ChannelDelete => {
|
||||
channel::handle_channel_delete(stream, seq, session_id, payload, crypto, state).await?;
|
||||
channel::handle_channel_delete(
|
||||
ctx.stream,
|
||||
ctx.seq,
|
||||
session_id,
|
||||
payload,
|
||||
ctx.crypto,
|
||||
ctx.state,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
PacketId::ChannelList => {
|
||||
channel::handle_channel_list(stream, seq, session_id, crypto, state).await?;
|
||||
channel::handle_channel_list(ctx.stream, ctx.seq, session_id, ctx.crypto, ctx.state)
|
||||
.await?;
|
||||
}
|
||||
PacketId::ChatMessage => {
|
||||
let m: ChatMessagePayload = serde_json::from_slice(payload)?;
|
||||
content::chat::handle(session_id, m, state).await?;
|
||||
content::chat::handle(session_id, m, ctx.state).await?;
|
||||
}
|
||||
PacketId::DmStart => {
|
||||
direct_message::handle_dm_start(stream, seq, session_id, payload, crypto, state)
|
||||
.await?;
|
||||
direct_message::handle_dm_start(
|
||||
ctx.stream,
|
||||
ctx.seq,
|
||||
session_id,
|
||||
payload,
|
||||
ctx.crypto,
|
||||
ctx.state,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
PacketId::DmMessage => {
|
||||
direct_message::handle_dm_message(stream, seq, session_id, payload, crypto, state)
|
||||
.await?;
|
||||
direct_message::handle_dm_message(
|
||||
ctx.stream,
|
||||
ctx.seq,
|
||||
session_id,
|
||||
payload,
|
||||
ctx.crypto,
|
||||
ctx.state,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
PacketId::DmHistory => {
|
||||
direct_message::handle_dm_history(stream, seq, session_id, payload, crypto, state)
|
||||
.await?;
|
||||
direct_message::handle_dm_history(
|
||||
ctx.stream,
|
||||
ctx.seq,
|
||||
session_id,
|
||||
payload,
|
||||
ctx.crypto,
|
||||
ctx.state,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
PacketId::DmReadAck => {
|
||||
direct_message::handle_dm_read_ack(stream, seq, session_id, payload, crypto, state)
|
||||
.await?;
|
||||
direct_message::handle_dm_read_ack(
|
||||
ctx.stream,
|
||||
ctx.seq,
|
||||
session_id,
|
||||
payload,
|
||||
ctx.crypto,
|
||||
ctx.state,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
PacketId::GuildCreate => {
|
||||
guild::handle_guild_create(stream, seq, session_id, payload, crypto, state).await?;
|
||||
guild::handle_guild_create(
|
||||
ctx.stream,
|
||||
ctx.seq,
|
||||
session_id,
|
||||
payload,
|
||||
ctx.crypto,
|
||||
ctx.state,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
PacketId::GuildDelete => {
|
||||
guild::handle_guild_delete(stream, seq, session_id, payload, crypto, state).await?;
|
||||
guild::handle_guild_delete(
|
||||
ctx.stream,
|
||||
ctx.seq,
|
||||
session_id,
|
||||
payload,
|
||||
ctx.crypto,
|
||||
ctx.state,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
PacketId::GuildList => {
|
||||
guild::handle_guild_list(stream, seq, session_id, crypto, state).await?;
|
||||
guild::handle_guild_list(ctx.stream, ctx.seq, session_id, ctx.crypto, ctx.state)
|
||||
.await?;
|
||||
}
|
||||
PacketId::GuildMemberJoin => {
|
||||
guild::handle_guild_member_join(stream, seq, session_id, payload, crypto, state)
|
||||
.await?;
|
||||
guild::handle_guild_member_join(
|
||||
ctx.stream,
|
||||
ctx.seq,
|
||||
session_id,
|
||||
payload,
|
||||
ctx.crypto,
|
||||
ctx.state,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
PacketId::GuildMemberLeave => {
|
||||
guild::handle_guild_member_leave(stream, seq, session_id, payload, crypto, state)
|
||||
.await?;
|
||||
guild::handle_guild_member_leave(
|
||||
ctx.stream,
|
||||
ctx.seq,
|
||||
session_id,
|
||||
payload,
|
||||
ctx.crypto,
|
||||
ctx.state,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
PacketId::GuildMemberKick => {
|
||||
guild::handle_guild_member_kick(stream, seq, session_id, payload, crypto, state)
|
||||
.await?;
|
||||
guild::handle_guild_member_kick(
|
||||
ctx.stream,
|
||||
ctx.seq,
|
||||
session_id,
|
||||
payload,
|
||||
ctx.crypto,
|
||||
ctx.state,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
PacketId::RoleCreate => {
|
||||
guild::handle_role_create(stream, seq, session_id, payload, crypto, state).await?;
|
||||
guild::handle_role_create(
|
||||
ctx.stream,
|
||||
ctx.seq,
|
||||
session_id,
|
||||
payload,
|
||||
ctx.crypto,
|
||||
ctx.state,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
PacketId::RoleDelete => {
|
||||
guild::handle_role_delete(stream, seq, session_id, payload, crypto, state).await?;
|
||||
guild::handle_role_delete(
|
||||
ctx.stream,
|
||||
ctx.seq,
|
||||
session_id,
|
||||
payload,
|
||||
ctx.crypto,
|
||||
ctx.state,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
PacketId::InviteCreate => {
|
||||
guild::handle_invite_create(stream, seq, session_id, payload, crypto, state).await?;
|
||||
guild::handle_invite_create(
|
||||
ctx.stream,
|
||||
ctx.seq,
|
||||
session_id,
|
||||
payload,
|
||||
ctx.crypto,
|
||||
ctx.state,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
PacketId::InviteAccept => {
|
||||
guild::handle_invite_accept(stream, seq, session_id, payload, crypto, state).await?;
|
||||
guild::handle_invite_accept(
|
||||
ctx.stream,
|
||||
ctx.seq,
|
||||
session_id,
|
||||
payload,
|
||||
ctx.crypto,
|
||||
ctx.state,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
PacketId::InviteDelete => {
|
||||
guild::handle_invite_delete(stream, seq, session_id, payload, crypto, state).await?;
|
||||
guild::handle_invite_delete(
|
||||
ctx.stream,
|
||||
ctx.seq,
|
||||
session_id,
|
||||
payload,
|
||||
ctx.crypto,
|
||||
ctx.state,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
PacketId::GuildAuditLogFetch => {
|
||||
guild::handle_audit_log_fetch(stream, seq, session_id, payload, crypto, state).await?;
|
||||
guild::handle_audit_log_fetch(
|
||||
ctx.stream,
|
||||
ctx.seq,
|
||||
session_id,
|
||||
payload,
|
||||
ctx.crypto,
|
||||
ctx.state,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
PacketId::GuildMemberListFetch => {
|
||||
guild::handle_member_list_fetch(stream, seq, session_id, payload, crypto, state)
|
||||
.await?;
|
||||
guild::handle_member_list_fetch(
|
||||
ctx.stream,
|
||||
ctx.seq,
|
||||
session_id,
|
||||
payload,
|
||||
ctx.crypto,
|
||||
ctx.state,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
PacketId::GuildRoleAssign => {
|
||||
guild::handle_role_assign(stream, seq, session_id, payload, crypto, state).await?;
|
||||
guild::handle_role_assign(
|
||||
ctx.stream,
|
||||
ctx.seq,
|
||||
session_id,
|
||||
payload,
|
||||
ctx.crypto,
|
||||
ctx.state,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
PacketId::GuildRoleUnassign => {
|
||||
guild::handle_role_unassign(stream, seq, session_id, payload, crypto, state).await?;
|
||||
guild::handle_role_unassign(
|
||||
ctx.stream,
|
||||
ctx.seq,
|
||||
session_id,
|
||||
payload,
|
||||
ctx.crypto,
|
||||
ctx.state,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
PacketId::GuildRoleListFetch => {
|
||||
guild::handle_role_list_fetch(stream, seq, session_id, payload, crypto, state).await?;
|
||||
guild::handle_role_list_fetch(
|
||||
ctx.stream,
|
||||
ctx.seq,
|
||||
session_id,
|
||||
payload,
|
||||
ctx.crypto,
|
||||
ctx.state,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
PacketId::PresenceUpdate => {
|
||||
content::presence::handle_presence_update(
|
||||
stream, seq, session_id, payload, crypto, state,
|
||||
ctx.stream,
|
||||
ctx.seq,
|
||||
session_id,
|
||||
payload,
|
||||
ctx.crypto,
|
||||
ctx.state,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
PacketId::PresenceSync => {
|
||||
content::presence::handle_presence_sync(stream, seq, session_id, crypto, state).await?;
|
||||
content::presence::handle_presence_sync(
|
||||
ctx.stream,
|
||||
ctx.seq,
|
||||
session_id,
|
||||
ctx.crypto,
|
||||
ctx.state,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
PacketId::FriendRequest => {
|
||||
friends::handle_friend_request(stream, seq, session_id, payload, crypto, state).await?;
|
||||
friends::handle_friend_request(
|
||||
ctx.stream,
|
||||
ctx.seq,
|
||||
session_id,
|
||||
payload,
|
||||
ctx.crypto,
|
||||
ctx.state,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
PacketId::FriendAccept => {
|
||||
friends::handle_friend_accept(stream, seq, session_id, payload, crypto, state).await?;
|
||||
friends::handle_friend_accept(
|
||||
ctx.stream,
|
||||
ctx.seq,
|
||||
session_id,
|
||||
payload,
|
||||
ctx.crypto,
|
||||
ctx.state,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
PacketId::FriendDecline => {
|
||||
friends::handle_friend_decline(stream, seq, session_id, payload, crypto, state).await?;
|
||||
friends::handle_friend_decline(
|
||||
ctx.stream,
|
||||
ctx.seq,
|
||||
session_id,
|
||||
payload,
|
||||
ctx.crypto,
|
||||
ctx.state,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
PacketId::FriendRemove => {
|
||||
friends::handle_friend_remove(stream, seq, session_id, payload, crypto, state).await?;
|
||||
friends::handle_friend_remove(
|
||||
ctx.stream,
|
||||
ctx.seq,
|
||||
session_id,
|
||||
payload,
|
||||
ctx.crypto,
|
||||
ctx.state,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
PacketId::FriendList => {
|
||||
friends::handle_friend_list(stream, seq, session_id, crypto, state).await?;
|
||||
friends::handle_friend_list(ctx.stream, ctx.seq, session_id, ctx.crypto, ctx.state)
|
||||
.await?;
|
||||
}
|
||||
PacketId::BlockUser => {
|
||||
friends::handle_block_user(stream, seq, session_id, payload, crypto, state).await?;
|
||||
friends::handle_block_user(
|
||||
ctx.stream,
|
||||
ctx.seq,
|
||||
session_id,
|
||||
payload,
|
||||
ctx.crypto,
|
||||
ctx.state,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
PacketId::UnblockUser => {
|
||||
friends::handle_unblock_user(stream, seq, session_id, payload, crypto, state).await?;
|
||||
friends::handle_unblock_user(
|
||||
ctx.stream,
|
||||
ctx.seq,
|
||||
session_id,
|
||||
payload,
|
||||
ctx.crypto,
|
||||
ctx.state,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
PacketId::BlockList => {
|
||||
friends::handle_block_list(stream, seq, session_id, crypto, state).await?;
|
||||
friends::handle_block_list(ctx.stream, ctx.seq, session_id, ctx.crypto, ctx.state)
|
||||
.await?;
|
||||
}
|
||||
PacketId::MessageReactionAdd => {
|
||||
let m: ReactionPayload = serde_json::from_slice(payload)?;
|
||||
content::reaction::handle_reaction_add(session_id, m, state).await?;
|
||||
content::reaction::handle_reaction_add(session_id, m, ctx.state).await?;
|
||||
}
|
||||
PacketId::MessageReactionRemove => {
|
||||
let m: ReactionPayload = serde_json::from_slice(payload)?;
|
||||
content::reaction::handle_reaction_remove(session_id, m, state).await?;
|
||||
content::reaction::handle_reaction_remove(session_id, m, ctx.state).await?;
|
||||
}
|
||||
PacketId::MessageEdit => {
|
||||
content::message_edit::handle_message_edit(session_id, payload, state).await?;
|
||||
content::message_edit::handle_message_edit(session_id, payload, ctx.state).await?;
|
||||
}
|
||||
PacketId::MessageDelete => {
|
||||
content::message_edit::handle_message_delete(session_id, payload, state).await?;
|
||||
content::message_edit::handle_message_delete(session_id, payload, ctx.state).await?;
|
||||
}
|
||||
PacketId::TypingStart => {
|
||||
content::handle_typing_start(session_id, payload, state).await?;
|
||||
content::handle_typing_start(session_id, payload, ctx.state).await?;
|
||||
}
|
||||
PacketId::ReadReceipt => {
|
||||
content::handle_read_receipt(stream, seq, session_id, payload, crypto, state).await?;
|
||||
content::handle_read_receipt(
|
||||
ctx.stream,
|
||||
ctx.seq,
|
||||
session_id,
|
||||
payload,
|
||||
ctx.crypto,
|
||||
ctx.state,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
PacketId::Disconnect => debug!("{addr} DISCONNECT"),
|
||||
other => debug!("{addr} unhandled {:?}", other),
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use anyhow::Result;
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
|
||||
use crate::{
|
||||
domain::session,
|
||||
|
|
@ -8,7 +8,7 @@ use crate::{
|
|||
};
|
||||
|
||||
pub async fn handle_friend_decline(
|
||||
stream: &mut TcpStream,
|
||||
stream: &mut (impl AsyncRead + AsyncWrite + Unpin),
|
||||
seq: &mut u32,
|
||||
session_id: &str,
|
||||
payload: &[u8],
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use anyhow::Result;
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
|
||||
use crate::{
|
||||
domain::session,
|
||||
|
|
@ -8,7 +8,7 @@ use crate::{
|
|||
};
|
||||
|
||||
pub async fn handle_friend_list(
|
||||
stream: &mut TcpStream,
|
||||
stream: &mut (impl AsyncRead + AsyncWrite + Unpin),
|
||||
seq: &mut u32,
|
||||
session_id: &str,
|
||||
crypto: &SessionCrypto,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use anyhow::Result;
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
|
||||
use crate::{
|
||||
domain::session,
|
||||
|
|
@ -11,7 +11,7 @@ use crate::{
|
|||
};
|
||||
|
||||
pub async fn handle_friend_remove(
|
||||
stream: &mut TcpStream,
|
||||
stream: &mut (impl AsyncRead + AsyncWrite + Unpin),
|
||||
seq: &mut u32,
|
||||
session_id: &str,
|
||||
payload: &[u8],
|
||||
|
|
@ -40,7 +40,7 @@ pub async fn handle_friend_remove(
|
|||
}
|
||||
|
||||
pub async fn handle_block_user(
|
||||
stream: &mut TcpStream,
|
||||
stream: &mut (impl AsyncRead + AsyncWrite + Unpin),
|
||||
seq: &mut u32,
|
||||
session_id: &str,
|
||||
payload: &[u8],
|
||||
|
|
@ -69,7 +69,7 @@ pub async fn handle_block_user(
|
|||
}
|
||||
|
||||
pub async fn handle_unblock_user(
|
||||
stream: &mut TcpStream,
|
||||
stream: &mut (impl AsyncRead + AsyncWrite + Unpin),
|
||||
seq: &mut u32,
|
||||
session_id: &str,
|
||||
payload: &[u8],
|
||||
|
|
@ -98,7 +98,7 @@ pub async fn handle_unblock_user(
|
|||
}
|
||||
|
||||
pub async fn handle_block_list(
|
||||
stream: &mut TcpStream,
|
||||
stream: &mut (impl AsyncRead + AsyncWrite + Unpin),
|
||||
seq: &mut u32,
|
||||
session_id: &str,
|
||||
crypto: &SessionCrypto,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ mod manage;
|
|||
mod requests;
|
||||
|
||||
use anyhow::Result;
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
|
||||
use crate::{
|
||||
net::io,
|
||||
|
|
@ -12,7 +12,7 @@ use crate::{
|
|||
};
|
||||
|
||||
async fn send_err(
|
||||
stream: &mut TcpStream,
|
||||
stream: &mut (impl AsyncRead + AsyncWrite + Unpin),
|
||||
seq: &mut u32,
|
||||
code: crate::proto::ErrorCode,
|
||||
msg: &str,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use anyhow::Result;
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
|
||||
use crate::{
|
||||
domain::session,
|
||||
|
|
@ -16,7 +16,7 @@ use crate::{
|
|||
use super::send_err;
|
||||
|
||||
pub async fn handle_friend_request(
|
||||
stream: &mut TcpStream,
|
||||
stream: &mut (impl AsyncRead + AsyncWrite + Unpin),
|
||||
seq: &mut u32,
|
||||
session_id: &str,
|
||||
payload: &[u8],
|
||||
|
|
@ -100,7 +100,7 @@ pub async fn handle_friend_request(
|
|||
}
|
||||
|
||||
pub async fn handle_friend_accept(
|
||||
stream: &mut TcpStream,
|
||||
stream: &mut (impl AsyncRead + AsyncWrite + Unpin),
|
||||
seq: &mut u32,
|
||||
session_id: &str,
|
||||
payload: &[u8],
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use anyhow::Result;
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
|
||||
use crate::{
|
||||
domain::permissions::Permissions,
|
||||
|
|
@ -12,7 +12,7 @@ use crate::{
|
|||
|
||||
/// Fetch audit log entries for a guild (admin-only: requires VIEW_AUDIT_LOG or owner).
|
||||
pub async fn handle_audit_log_fetch(
|
||||
stream: &mut TcpStream,
|
||||
stream: &mut (impl AsyncRead + AsyncWrite + Unpin),
|
||||
seq: &mut u32,
|
||||
session_id: &str,
|
||||
payload: &[u8],
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use anyhow::Result;
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
use tracing::debug;
|
||||
|
||||
use crate::{
|
||||
|
|
@ -11,7 +11,7 @@ use crate::{
|
|||
use super::send_err;
|
||||
|
||||
pub async fn handle_guild_create(
|
||||
stream: &mut TcpStream,
|
||||
stream: &mut (impl AsyncRead + AsyncWrite + Unpin),
|
||||
seq: &mut u32,
|
||||
session_id: &str,
|
||||
payload: &[u8],
|
||||
|
|
@ -67,7 +67,7 @@ pub async fn handle_guild_create(
|
|||
}
|
||||
|
||||
pub async fn handle_guild_delete(
|
||||
stream: &mut TcpStream,
|
||||
stream: &mut (impl AsyncRead + AsyncWrite + Unpin),
|
||||
seq: &mut u32,
|
||||
session_id: &str,
|
||||
payload: &[u8],
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use anyhow::Result;
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
|
||||
use crate::{
|
||||
domain::{permissions::Permissions, session},
|
||||
|
|
@ -13,7 +13,7 @@ use crate::{
|
|||
use super::{now_ms, send_err};
|
||||
|
||||
pub async fn handle_invite_create(
|
||||
stream: &mut TcpStream,
|
||||
stream: &mut (impl AsyncRead + AsyncWrite + Unpin),
|
||||
seq: &mut u32,
|
||||
session_id: &str,
|
||||
payload: &[u8],
|
||||
|
|
@ -89,7 +89,7 @@ pub async fn handle_invite_create(
|
|||
}
|
||||
|
||||
pub async fn handle_invite_accept(
|
||||
stream: &mut TcpStream,
|
||||
stream: &mut (impl AsyncRead + AsyncWrite + Unpin),
|
||||
seq: &mut u32,
|
||||
session_id: &str,
|
||||
payload: &[u8],
|
||||
|
|
@ -164,7 +164,7 @@ pub async fn handle_invite_accept(
|
|||
}
|
||||
|
||||
pub async fn handle_invite_delete(
|
||||
stream: &mut TcpStream,
|
||||
stream: &mut (impl AsyncRead + AsyncWrite + Unpin),
|
||||
seq: &mut u32,
|
||||
session_id: &str,
|
||||
payload: &[u8],
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use anyhow::Result;
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
|
||||
use crate::{
|
||||
domain::session,
|
||||
|
|
@ -8,7 +8,7 @@ use crate::{
|
|||
};
|
||||
|
||||
pub async fn handle_guild_list(
|
||||
stream: &mut TcpStream,
|
||||
stream: &mut (impl AsyncRead + AsyncWrite + Unpin),
|
||||
seq: &mut u32,
|
||||
session_id: &str,
|
||||
crypto: &SessionCrypto,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use anyhow::Result;
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
|
||||
use crate::{
|
||||
domain::{permissions::Permissions, session},
|
||||
|
|
@ -13,7 +13,7 @@ use crate::{
|
|||
use super::send_err;
|
||||
|
||||
pub async fn handle_guild_member_join(
|
||||
stream: &mut TcpStream,
|
||||
stream: &mut (impl AsyncRead + AsyncWrite + Unpin),
|
||||
seq: &mut u32,
|
||||
session_id: &str,
|
||||
payload: &[u8],
|
||||
|
|
@ -63,7 +63,7 @@ pub async fn handle_guild_member_join(
|
|||
}
|
||||
|
||||
pub async fn handle_guild_member_leave(
|
||||
stream: &mut TcpStream,
|
||||
stream: &mut (impl AsyncRead + AsyncWrite + Unpin),
|
||||
seq: &mut u32,
|
||||
session_id: &str,
|
||||
payload: &[u8],
|
||||
|
|
@ -96,7 +96,7 @@ pub async fn handle_guild_member_leave(
|
|||
}
|
||||
|
||||
pub async fn handle_guild_member_kick(
|
||||
stream: &mut TcpStream,
|
||||
stream: &mut (impl AsyncRead + AsyncWrite + Unpin),
|
||||
seq: &mut u32,
|
||||
session_id: &str,
|
||||
payload: &[u8],
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use anyhow::Result;
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
|
||||
use crate::{
|
||||
domain::{permissions::Permissions, session},
|
||||
|
|
@ -15,7 +15,7 @@ use super::{require_perm, send_err};
|
|||
|
||||
/// Fetch the member list for a guild (visible to all members).
|
||||
pub async fn handle_member_list_fetch(
|
||||
stream: &mut TcpStream,
|
||||
stream: &mut (impl AsyncRead + AsyncWrite + Unpin),
|
||||
seq: &mut u32,
|
||||
session_id: &str,
|
||||
payload: &[u8],
|
||||
|
|
@ -65,7 +65,7 @@ pub async fn handle_member_list_fetch(
|
|||
|
||||
/// Assign a role to a user (admin only: requires MANAGE_ROLES).
|
||||
pub async fn handle_role_assign(
|
||||
stream: &mut TcpStream,
|
||||
stream: &mut (impl AsyncRead + AsyncWrite + Unpin),
|
||||
seq: &mut u32,
|
||||
session_id: &str,
|
||||
payload: &[u8],
|
||||
|
|
@ -129,7 +129,7 @@ pub async fn handle_role_assign(
|
|||
|
||||
/// Remove a role from a user (admin only: requires MANAGE_ROLES).
|
||||
pub async fn handle_role_unassign(
|
||||
stream: &mut TcpStream,
|
||||
stream: &mut (impl AsyncRead + AsyncWrite + Unpin),
|
||||
seq: &mut u32,
|
||||
session_id: &str,
|
||||
payload: &[u8],
|
||||
|
|
@ -192,7 +192,7 @@ pub async fn handle_role_unassign(
|
|||
|
||||
/// Fetch all roles defined in a guild (visible to all members).
|
||||
pub async fn handle_role_list_fetch(
|
||||
stream: &mut TcpStream,
|
||||
stream: &mut (impl AsyncRead + AsyncWrite + Unpin),
|
||||
seq: &mut u32,
|
||||
session_id: &str,
|
||||
payload: &[u8],
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ mod members_list;
|
|||
mod roles;
|
||||
|
||||
use anyhow::Result;
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
|
||||
use crate::{
|
||||
domain::permissions::Permissions,
|
||||
|
|
@ -16,7 +16,7 @@ use crate::{
|
|||
};
|
||||
|
||||
async fn send_err(
|
||||
stream: &mut TcpStream,
|
||||
stream: &mut (impl AsyncRead + AsyncWrite + Unpin),
|
||||
seq: &mut u32,
|
||||
code: crate::proto::ErrorCode,
|
||||
msg: &str,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use anyhow::Result;
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
|
||||
use crate::{
|
||||
domain::{permissions::Permissions, session},
|
||||
|
|
@ -10,7 +10,7 @@ use crate::{
|
|||
use super::send_err;
|
||||
|
||||
pub async fn handle_role_create(
|
||||
stream: &mut TcpStream,
|
||||
stream: &mut (impl AsyncRead + AsyncWrite + Unpin),
|
||||
seq: &mut u32,
|
||||
session_id: &str,
|
||||
payload: &[u8],
|
||||
|
|
@ -73,7 +73,7 @@ pub async fn handle_role_create(
|
|||
}
|
||||
|
||||
pub async fn handle_role_delete(
|
||||
stream: &mut TcpStream,
|
||||
stream: &mut (impl AsyncRead + AsyncWrite + Unpin),
|
||||
seq: &mut u32,
|
||||
session_id: &str,
|
||||
payload: &[u8],
|
||||
|
|
|
|||
|
|
@ -10,12 +10,12 @@ pub mod run;
|
|||
pub use dispatch::dispatch;
|
||||
pub use run::run_session;
|
||||
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
|
||||
use crate::{net::state::State, proto::SessionCrypto};
|
||||
|
||||
pub struct Ctx<'a> {
|
||||
pub stream: &'a mut TcpStream,
|
||||
pub struct Ctx<'a, S: AsyncRead + AsyncWrite + Unpin> {
|
||||
pub stream: &'a mut S,
|
||||
pub seq: &'a mut u32,
|
||||
pub crypto: &'a SessionCrypto,
|
||||
pub state: &'a State,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use anyhow::Result;
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
use tokio::sync::broadcast;
|
||||
use tracing::warn;
|
||||
|
||||
|
|
@ -10,8 +10,8 @@ use crate::{
|
|||
|
||||
use super::{Ctx, deliver::deliver_encrypted, dispatch};
|
||||
|
||||
pub async fn run_session(
|
||||
stream: &mut TcpStream,
|
||||
pub async fn run_session<S: AsyncRead + AsyncWrite + Unpin>(
|
||||
stream: &mut S,
|
||||
addr: std::net::SocketAddr,
|
||||
seq: &mut u32,
|
||||
session_id: &str,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue