Skip to content

Commit

Permalink
Implement WALLOPS
Browse files Browse the repository at this point in the history
  • Loading branch information
w4 committed Jan 29, 2024
1 parent 0a5ef8e commit 722ae31
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 15 deletions.
4 changes: 2 additions & 2 deletions rustfmt.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
edition = "2021"
## not yet supported on stable
#imports_granularity = "Crate"
imports_granularity = "Crate"
newline_style = "Unix"
## not yet supported on stable
#group_imports = "StdExternalCrate"
group_imports = "StdExternalCrate"
use_field_init_shorthand = true
14 changes: 8 additions & 6 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ use crate::{
channel::Channel,
connection::{
sasl::SaslAlreadyAuthenticated, Capability, InitiatedConnection, MessageSink,
NickNotOwnedByUser,
NickNotOwnedByUser, UserMode,
},
messages::{
Broadcast, ChannelFetchTopic, ChannelFetchWhoList, ChannelInvite, ChannelJoin,
ChannelKickUser, ChannelList, ChannelMemberList, ChannelMessage, ChannelPart,
ChannelSetMode, ChannelUpdateTopic, ClientAway, ConnectedChannels, FetchClientDetails,
FetchUserPermission, FetchWhoList, FetchWhois, MessageKind, PrivateMessage,
ServerAdminInfo, ServerDisconnect, ServerFetchMotd, ServerListUsers, UserKickedFromChannel,
UserNickChange, UserNickChangeInternal,
UserNickChange, UserNickChangeInternal, Wallops,
},
persistence::{
events::{
Expand Down Expand Up @@ -624,9 +624,6 @@ impl StreamHandler<Result<irc_proto::Message, ProtocolError>> for Client {
// https://modern.ircdocs.horse/
#[allow(clippy::match_same_arms)]
match item.command {
Command::USER(_, _, _) | Command::PASS(_) | Command::CAP(_, _, _, _) => {
// these were already handled by `negotiate_client_connection`
}
Command::NICK(new_nick) => {
ctx.notify(UserNickChangeInternal {
old_nick: self.connection.nick.to_string(),
Expand Down Expand Up @@ -883,7 +880,12 @@ impl StreamHandler<Result<irc_proto::Message, ProtocolError>> for Client {
Command::DIE => {}
Command::RESTART => {}
Command::USERS(_) => {}
Command::WALLOPS(_) => {}
Command::WALLOPS(message) if self.connection.mode.contains(UserMode::OPER) => {
self.server.do_send(Wallops {
span: Span::current(),
message,
});
}
Command::USERHOST(_) => {}
Command::SAJOIN(_, _) => {}
Command::SAMODE(_, _, _) => {}
Expand Down
29 changes: 23 additions & 6 deletions src/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ pub struct ConnectionRequest {
host: Option<SocketAddr>,
nick: Option<String>,
user: Option<String>,
mode: Option<String>,
real_name: Option<String>,
user_id: Option<UserId>,
capabilities: Capability,
Expand All @@ -55,7 +54,7 @@ pub struct InitiatedConnection {
pub host: SocketAddr,
pub nick: String,
pub user: String,
pub mode: String,
pub mode: UserMode,
pub real_name: String,
pub user_id: UserId,
pub capabilities: Capability,
Expand All @@ -82,7 +81,6 @@ impl TryFrom<ConnectionRequest> for InitiatedConnection {
host: Some(host),
nick: Some(nick),
user: Some(user),
mode: Some(mode),
real_name: Some(real_name),
user_id: Some(user_id),
capabilities,
Expand All @@ -95,7 +93,7 @@ impl TryFrom<ConnectionRequest> for InitiatedConnection {
host,
nick,
user,
mode,
mode: UserMode::empty(),
real_name,
user_id,
capabilities,
Expand Down Expand Up @@ -138,9 +136,8 @@ pub async fn negotiate_client_connection(
match msg.command {
Command::PASS(_) => {}
Command::NICK(nick) => request.nick = Some(nick),
Command::USER(_user, mode, real_name) => {
Command::USER(_user, _mode, real_name) => {
// we ignore the user here, as it will be set by the AUTHENTICATE command
request.mode = Some(mode);
request.real_name = Some(real_name);
}
Command::CAP(_, CapSubCommand::LIST | CapSubCommand::LS, _, _) => {
Expand Down Expand Up @@ -279,6 +276,26 @@ bitflags! {
const USERHOST_IN_NAMES = 0b0000_0000_0000_0000_0000_0000_0000_0001;
const SERVER_TIME = 0b0000_0000_0000_0000_0000_0000_0000_0010;
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
pub struct UserMode: u32 {
/// a - user is flagged as away
const AWAY = 0b0000_0000_0000_0000_0000_0000_0000_0001;
/// i - marks a users as invisible
const INVISIBLE = 0b0000_0000_0000_0000_0000_0000_0000_0010;
/// w - user receives wallops
const WALLOPS = 0b0000_0000_0000_0000_0000_0000_0000_0100;
/// r - restricted user connection
const RESTRICTED = 0b0000_0000_0000_0000_0000_0000_0000_1000;
/// o - operator flag
const OPER = 0b0000_0000_0000_0000_0000_0000_0001_0000;
/// O - local operator flag
const LOCAL_OPER = 0b0000_0000_0000_0000_0000_0000_0010_0000;
/// s - marks a user for receipt of server notices
const SERVER_NOTICES = 0b0000_0000_0000_0000_0000_0000_0100_0000;
/// x - masked hostname
const MASKED_HOST = 0b0000_0000_0000_0000_0000_0000_1000_0000;
}
}

impl Capability {
Expand Down
7 changes: 7 additions & 0 deletions src/messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ pub struct UserNickChange {
pub span: Span,
}

#[derive(Message, Clone)]
#[rtype(result = "()")]
pub struct Wallops {
pub message: String,
pub span: Span,
}

/// List all the channels a user is connected to
#[derive(Message, Clone)]
#[rtype(result = "Vec<(crate::channel::permissions::Permission, String)>")]
Expand Down
25 changes: 24 additions & 1 deletion src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,13 @@ use crate::{
channel::{permissions::Permission, Channel, ChannelId},
client::Client,
config::Config,
connection::InitiatedConnection,
connection::{InitiatedConnection, UserMode},
messages::{
Broadcast, ChannelFetchTopic, ChannelFetchWhoList, ChannelJoin, ChannelList,
ChannelMemberList, ClientAway, ConnectedChannels, FetchClientByNick, FetchWhoList,
FetchWhois, MessageKind, PrivateMessage, ServerAdminInfo, ServerDisconnect,
ServerFetchMotd, ServerListUsers, UserConnected, UserNickChange, UserNickChangeInternal,
Wallops,
},
persistence::Persistence,
server::response::{AdminInfo, ListUsers, Motd, WhoList, Whois},
Expand Down Expand Up @@ -135,6 +136,28 @@ impl Handler<UserConnected> for Server {
}
}

impl Handler<Wallops> for Server {
type Result = ();

#[instrument(parent = &msg.span, skip_all)]
fn handle(&mut self, msg: Wallops, _ctx: &mut Self::Context) -> Self::Result {
for (handle, conn) in &self.clients {
if !conn.mode.contains(UserMode::WALLOPS) {
continue;
}

handle.do_send(Broadcast {
message: Message {
tags: None,
prefix: Some(Prefix::ServerName(SERVER_NAME.to_string())),
command: Command::WALLOPS(msg.message.clone()),
},
span: msg.span.clone(),
});
}
}
}

/// Returns the MOTD when requested.
impl Handler<ServerFetchMotd> for Server {
type Result = MessageResult<ServerFetchMotd>;
Expand Down

0 comments on commit 722ae31

Please sign in to comment.