ping.rs

 1use try_from::TryFrom;
 2
 3use plugin::PluginProxy;
 4use event::{Event, Priority, Propagation};
 5use error::Error;
 6use jid::Jid;
 7
 8use plugins::stanza::Iq;
 9use plugins::disco::DiscoPlugin;
10use xmpp_parsers::iq::{IqType, IqGetPayload};
11use xmpp_parsers::ping::Ping;
12use xmpp_parsers::ns;
13
14#[derive(Debug)]
15pub struct PingEvent {
16    pub from: Jid,
17    pub id: String,
18}
19
20impl Event for PingEvent {}
21
22pub struct PingPlugin {
23    proxy: PluginProxy,
24}
25
26impl PingPlugin {
27    pub fn new() -> PingPlugin {
28        PingPlugin {
29            proxy: PluginProxy::new(),
30        }
31    }
32
33    // TODO: make that called automatically after plugins are created.
34    pub fn init(&self) {
35        if let Some(disco) = self.proxy.plugin::<DiscoPlugin>() {
36            disco.add_feature(ns::PING);
37        } else {
38            panic!("Please handle dependencies in the correct order.");
39        }
40    }
41
42    // TODO: make that called automatically before removal.
43    pub fn deinit(&self) {
44        if let Some(disco) = self.proxy.plugin::<DiscoPlugin>() {
45            disco.remove_feature(ns::PING);
46        } else {
47            panic!("Please handle dependencies in the correct order.");
48        }
49    }
50
51    pub fn send_ping(&self, to: &Jid) -> Result<(), Error> {
52        let to = to.clone();
53        self.proxy.send(Iq {
54            from: None,
55            to: Some(to),
56            id: Some(self.proxy.gen_id()),
57            payload: IqType::Get(IqGetPayload::Ping(Ping).into()),
58        }.into());
59        Ok(())
60    }
61
62    fn handle_iq(&self, iq: &Iq) -> Propagation {
63        let iq = iq.clone();
64        if let IqType::Get(payload) = iq.payload {
65            // TODO: use an intermediate plugin to parse this payload.
66            if let Ok(IqGetPayload::Ping(_)) = IqGetPayload::try_from(payload) {
67                self.proxy.dispatch(PingEvent { // TODO: safety!!!
68                    from: iq.from.unwrap(),
69                    id: iq.id.unwrap(),
70                });
71                return Propagation::Stop;
72            }
73        }
74        Propagation::Continue
75    }
76
77    fn reply_ping(&self, ping: &PingEvent) -> Propagation {
78        self.proxy.send(Iq {
79            from: None,
80            to: Some(ping.from.to_owned()),
81            id: Some(ping.id.to_owned()),
82            payload: IqType::Result(None),
83        }.into());
84        Propagation::Continue
85    }
86}
87
88impl_plugin!(PingPlugin, proxy, [
89    (Iq, Priority::Default) => handle_iq,
90    (PingEvent, Priority::Default) => reply_ping,
91]);