handlers: pinging room unsupported until affiliations are implemented
Signed-off-by: Maxime “pep” Buquet <pep@bouah.net>
This commit is contained in:
parent
2a2d8cd051
commit
132757c8b3
3 changed files with 97 additions and 28 deletions
|
@ -38,6 +38,8 @@ pub enum Error {
|
||||||
SecondarySession(Session),
|
SecondarySession(Session),
|
||||||
/// Raised when a JID was supposed to be present
|
/// Raised when a JID was supposed to be present
|
||||||
MissingJid,
|
MissingJid,
|
||||||
|
/// Unhandled Iq with error description
|
||||||
|
UnhandledIq(String),
|
||||||
/// Jid Parse errors
|
/// Jid Parse errors
|
||||||
Jid(Box<JidParseError>),
|
Jid(Box<JidParseError>),
|
||||||
/// TokioXMPP errors
|
/// TokioXMPP errors
|
||||||
|
@ -58,6 +60,7 @@ impl fmt::Display for Error {
|
||||||
Error::ParticipantNotFound(err) => write!(f, "Participant not found: {}", err),
|
Error::ParticipantNotFound(err) => write!(f, "Participant not found: {}", err),
|
||||||
Error::SecondarySession(err) => write!(f, "Secondary session: {:?}", err),
|
Error::SecondarySession(err) => write!(f, "Secondary session: {:?}", err),
|
||||||
Error::MissingJid => write!(f, "Missing JID"),
|
Error::MissingJid => write!(f, "Missing JID"),
|
||||||
|
Error::UnhandledIq(err) => write!(f, "Unhandled Iq: {:?}", err),
|
||||||
Error::Jid(err) => write!(f, "Jid Parse error: {}", err),
|
Error::Jid(err) => write!(f, "Jid Parse error: {}", err),
|
||||||
Error::Xmpp(err) => write!(f, "XMPP error: {}", err),
|
Error::Xmpp(err) => write!(f, "XMPP error: {}", err),
|
||||||
Error::Parser(err) => write!(f, "Parser error: {}", err),
|
Error::Parser(err) => write!(f, "Parser error: {}", err),
|
||||||
|
|
|
@ -91,7 +91,7 @@ async fn handle_iq_ping<C: ComponentTrait>(
|
||||||
let success = Iq::empty_result(iq.from.as_ref().unwrap().clone(), iq.id.clone())
|
let success = Iq::empty_result(iq.from.as_ref().unwrap().clone(), iq.id.clone())
|
||||||
.with_to(from.clone());
|
.with_to(from.clone());
|
||||||
|
|
||||||
// Pinging a participant
|
// Pinging a participant. The resource needs to be currently joined.
|
||||||
if let Jid::Full(participant) = to.clone() {
|
if let Jid::Full(participant) = to.clone() {
|
||||||
// TODO: Reply from participant if joined and nick is correct
|
// TODO: Reply from participant if joined and nick is correct
|
||||||
let bare = BareJid::from(to.clone());
|
let bare = BareJid::from(to.clone());
|
||||||
|
@ -112,17 +112,12 @@ async fn handle_iq_ping<C: ComponentTrait>(
|
||||||
let domain = BareJid::from_str(&to.domain).unwrap();
|
let domain = BareJid::from_str(&to.domain).unwrap();
|
||||||
let success = success.clone().with_from(Jid::Bare(domain));
|
let success = success.clone().with_from(Jid::Bare(domain));
|
||||||
component.send_stanza(success).await?;
|
component.send_stanza(success).await?;
|
||||||
// Pinging a room
|
// Pinging a room. User is required to have an affiliation other than none if
|
||||||
|
// member-only.
|
||||||
} else {
|
} else {
|
||||||
if let Some(room) = rooms.get(&to) {
|
return Err(Error::UnhandledIq(String::from(
|
||||||
if room.is_joined(&from) {
|
"Pinging a room is not yet supported",
|
||||||
let success = success.clone().with_from(Jid::Bare(to));
|
)));
|
||||||
component.send_stanza(success).await?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let success = success.clone().with_from(Jid::Bare(to));
|
|
||||||
component.send_stanza(success).await?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
@ -158,23 +153,39 @@ async fn handle_iq<C: ComponentTrait>(
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
match iq.payload {
|
match iq.payload {
|
||||||
IqType::Get(ref payload) => {
|
IqType::Get(ref payload) => {
|
||||||
|
let iq_result = {
|
||||||
if payload.is("query", ns::DISCO_INFO) {
|
if payload.is("query", ns::DISCO_INFO) {
|
||||||
handle_iq_disco(component, iq.clone(), payload.clone()).await?
|
handle_iq_disco(component, iq.clone(), payload.clone()).await
|
||||||
} else if payload.is("ping", ns::PING) {
|
} else if payload.is("ping", ns::PING) {
|
||||||
handle_iq_ping(component, iq.clone(), payload.clone(), rooms).await?
|
handle_iq_ping(component, iq.clone(), payload.clone(), rooms).await
|
||||||
} else {
|
} else {
|
||||||
// We MUST answer unhandled get iqs with a service-unavailable error.
|
// We MUST answer unhandled get iqs with a service-unavailable error.
|
||||||
let error = StanzaError::new(
|
handle_unhandled_iq(
|
||||||
ErrorType::Cancel,
|
component,
|
||||||
DefinedCondition::ServiceUnavailable,
|
iq.id.clone(),
|
||||||
|
iq.to.clone().unwrap(),
|
||||||
|
iq.from.clone().unwrap(),
|
||||||
"en",
|
"en",
|
||||||
"No handler defined for this kind of iq.",
|
"No handler defined for this kind of iq.",
|
||||||
);
|
)
|
||||||
let iq: Element = Iq::from_error(iq.id, error)
|
.await
|
||||||
.with_from(iq.to.unwrap())
|
}
|
||||||
.with_to(iq.from.unwrap())
|
};
|
||||||
.into();
|
|
||||||
component.send_stanza(iq).await?;
|
match iq_result {
|
||||||
|
Ok(()) => (),
|
||||||
|
Err(Error::UnhandledIq(desc)) => {
|
||||||
|
handle_unhandled_iq(
|
||||||
|
component,
|
||||||
|
iq.id,
|
||||||
|
iq.to.unwrap(),
|
||||||
|
iq.from.unwrap(),
|
||||||
|
"en",
|
||||||
|
desc.as_str(),
|
||||||
|
)
|
||||||
|
.await?
|
||||||
|
}
|
||||||
|
err => err?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => error!("Not handled iq: {:?}", iq),
|
_ => error!("Not handled iq: {:?}", iq),
|
||||||
|
@ -183,6 +194,24 @@ async fn handle_iq<C: ComponentTrait>(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn handle_unhandled_iq<C: ComponentTrait>(
|
||||||
|
component: &mut C,
|
||||||
|
id: String,
|
||||||
|
from: Jid,
|
||||||
|
to: Jid,
|
||||||
|
lang: &str,
|
||||||
|
desc: &str,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
let error = StanzaError::new(
|
||||||
|
ErrorType::Cancel,
|
||||||
|
DefinedCondition::ServiceUnavailable,
|
||||||
|
lang,
|
||||||
|
desc,
|
||||||
|
);
|
||||||
|
let iq: Element = Iq::from_error(id, error).with_from(from).with_to(to).into();
|
||||||
|
component.send_stanza(iq).await
|
||||||
|
}
|
||||||
|
|
||||||
async fn handle_presence<C: ComponentTrait>(
|
async fn handle_presence<C: ComponentTrait>(
|
||||||
component: &mut C,
|
component: &mut C,
|
||||||
presence: Presence,
|
presence: Presence,
|
||||||
|
|
|
@ -150,3 +150,40 @@ async fn test_self_ping_participant_non_existing() {
|
||||||
|
|
||||||
handle_stanza(&mut component, &mut rooms).await.unwrap();
|
handle_stanza(&mut component, &mut rooms).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_ping_room() {
|
||||||
|
let realjid1 = Jid::Full(FullJid::from_str("foo@bar/qxx").unwrap());
|
||||||
|
let roomjid = COMPONENT_JID.clone().with_node("room");
|
||||||
|
|
||||||
|
let ping: Element = Iq {
|
||||||
|
from: Some(realjid1.clone()),
|
||||||
|
to: Some(Jid::Bare(roomjid.clone())),
|
||||||
|
id: String::from("ping"),
|
||||||
|
payload: IqType::Get(Ping {}.into()),
|
||||||
|
}
|
||||||
|
.into();
|
||||||
|
|
||||||
|
let mut component = TestComponent::new(vec![ping]);
|
||||||
|
let mut rooms: HashMap<BareJid, Room> = HashMap::new();
|
||||||
|
|
||||||
|
component.expect_iq(
|
||||||
|
realjid1.clone(),
|
||||||
|
move |iq| {
|
||||||
|
let from = roomjid.clone();
|
||||||
|
let to = realjid1.clone();
|
||||||
|
assert_eq!(iq.from.unwrap(), Jid::Bare(from));
|
||||||
|
assert_eq!(iq.to.unwrap(), to);
|
||||||
|
match iq.payload {
|
||||||
|
IqType::Error(err) => {
|
||||||
|
assert_eq!(err.type_, ErrorType::Cancel);
|
||||||
|
assert_eq!(err.defined_condition, DefinedCondition::ServiceUnavailable);
|
||||||
|
}
|
||||||
|
payload => panic!("Unexpected payload for iq ping reply: {:?}", payload),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ServiceUnavailable iq error",
|
||||||
|
);
|
||||||
|
|
||||||
|
handle_stanza(&mut component, &mut rooms).await.unwrap();
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue