ellidri/state/
capabilities.rs1use crate::client::cap;
6use crate::lines;
7use crate::message::{Command, rpl};
8use super::{CommandContext, HandlerResult as Result};
9
10impl super::StateInner {
11 fn cmd_cap_list(&self, ctx: CommandContext<'_>) -> Result {
12 let client = &self.clients[ctx.addr];
13 client.write_enabled_capabilities(ctx.rb);
14 Ok(())
15 }
16
17 fn cmd_cap_ls(&mut self, ctx: CommandContext<'_>, version: &str) -> Result {
18 let client = self.clients.get_mut(ctx.addr).unwrap();
19 client.set_cap_version(version);
20 let mut msg = ctx.rb.reply(Command::Cap).param("LS");
21 let mut trailing = msg.raw_trailing_param();
22
23 trailing.push_str(cap::LS_COMMON);
24 if self.auth_provider.is_available() {
25 trailing.push_str(" sasl");
26 if client.capabilities.v302 {
27 trailing.push('=');
28 self.auth_provider.write_mechanisms(&mut trailing);
29 }
30 }
31
32 Ok(())
33 }
34
35 fn cmd_cap_req(&mut self, ctx: CommandContext<'_>, capabilities: &str) -> Result {
36 let client = self.clients.get_mut(ctx.addr).unwrap();
37 if !cap::are_supported(capabilities) {
38 ctx.rb.reply(Command::Cap).param("NAK").trailing_param(capabilities);
39 return Err(());
40 }
41 client.update_capabilities(capabilities);
42 ctx.rb.reply(Command::Cap).param("ACK").trailing_param(capabilities);
43 Ok(())
44 }
45
46 pub fn cmd_cap(&mut self, ctx: CommandContext<'_>, params: &[&str]) -> Result {
47 match params[0] {
48 "END" => Ok(()),
49 "LIST" => self.cmd_cap_list(ctx),
50 "LS" => self.cmd_cap_ls(ctx, *params.get(1).unwrap_or(&"")),
51 "REQ" => self.cmd_cap_req(ctx, *params.get(1).unwrap_or(&"")),
52 _ => {
53 log::debug!("{}: Bad command", ctx.addr);
54 ctx.rb.reply(rpl::ERR_INVALIDCAPCMD)
55 .param(params[0])
56 .trailing_param(lines::UNKNOWN_COMMAND);
57 Err(())
58 }
59 }
60 }
61}