1use std::convert::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, IqPayload};
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 // TODO: use a generic way to generate ids.
57 id: Some(String::from("id")),
58 payload: IqType::Get(IqPayload::Ping(Ping).into()),
59 }.into());
60 Ok(())
61 }
62
63 fn handle_iq(&self, iq: &Iq) -> Propagation {
64 let iq = iq.clone();
65 if let IqType::Get(payload) = iq.payload {
66 // TODO: use an intermediate plugin to parse this payload.
67 if let Ok(IqPayload::Ping(_)) = IqPayload::try_from(payload) {
68 self.proxy.dispatch(PingEvent { // TODO: safety!!!
69 from: iq.from.unwrap(),
70 id: iq.id.unwrap(),
71 });
72 return Propagation::Stop;
73 }
74 }
75 Propagation::Continue
76 }
77
78 fn reply_ping(&self, ping: &PingEvent) -> Propagation {
79 self.proxy.send(Iq {
80 from: None,
81 to: Some(ping.from.to_owned()),
82 id: Some(ping.id.to_owned()),
83 payload: IqType::Result(None),
84 }.into());
85 Propagation::Continue
86 }
87}
88
89impl_plugin!(PingPlugin, proxy, [
90 (Iq, Priority::Default) => handle_iq,
91 (PingEvent, Priority::Default) => reply_ping,
92]);