diff --git a/src/handlers/presence.rs b/src/handlers/presence.rs index 7af8e78..ccd401c 100644 --- a/src/handlers/presence.rs +++ b/src/handlers/presence.rs @@ -84,7 +84,7 @@ async fn handle_presence_full_available( debug!("Presence received to existing room: {}", &roomjid); if let ControlFlow::Break(_) = muc { // <{muc}x/> was found - match room.add_session(component, *presence.clone()).await { + match room.add_session(component, presence.clone()).await { Ok(_) => (), Err(Error::NickAlreadyAssigned(nick)) => { let error = Presence::new(PresenceType::Error) @@ -103,7 +103,7 @@ async fn handle_presence_full_available( } } else if let ControlFlow::Continue(_) = muc { // <{muc}x/> wasn't found - match room.update_presence(component, *presence.clone()).await { + match room.update_presence(component, presence.clone()).await { Ok(()) => (), Err(Error::ParticipantNotFound(_)) => { let error = Presence::new(PresenceType::Unavailable) @@ -131,9 +131,7 @@ async fn handle_presence_full_available( } else { debug!("Presence received to new room: {}", &roomjid); let mut room = Room::new(roomjid.clone()); - room.add_session(component, *presence.clone()) - .await - .unwrap(); + room.add_session(component, presence.clone()).await.unwrap(); let _ = rooms.insert(roomjid, room); } @@ -165,7 +163,7 @@ async fn handle_presence_full_unavailable( ) .into()]); if let Some(mut room) = rooms.remove(&roomjid) { - match room.remove_session(component, *presence.clone()).await { + match room.remove_session(component, presence.clone()).await { Ok(()) => (), Err(Error::NonexistantSession(_)) => { component.send_stanza(error).await.unwrap(); diff --git a/src/occupant.rs b/src/occupant.rs index b744930..e82c42a 100644 --- a/src/occupant.rs +++ b/src/occupant.rs @@ -14,11 +14,12 @@ // along with this program. If not, see . use crate::error::Error; +use crate::presence::PresenceFull; use crate::session::{Nick, Session}; use std::iter::IntoIterator; -use xmpp_parsers::{presence::Presence, BareJid, FullJid, Jid}; +use xmpp_parsers::{BareJid, FullJid, Jid}; /// An occupant in a room. May contain multiple sessions (Multi-Session Nicks) #[derive(Debug, Clone, PartialEq)] @@ -32,7 +33,7 @@ pub struct Occupant { impl Occupant { /// New occupant - pub fn new(presence: Presence) -> Result { + pub fn new(presence: PresenceFull) -> Result { let participant = presence.to.clone().map(FullJid::try_from).unwrap().unwrap(); let session = Session::try_from(presence)?; Ok(Occupant { @@ -50,7 +51,7 @@ impl Occupant { } /// Add a new session to the occupant - pub fn add_session(&mut self, presence: Presence) -> Result<(), Error> { + pub fn add_session(&mut self, presence: PresenceFull) -> Result<(), Error> { let new_session = Session::try_from(presence)?; if BareJid::from(new_session.real().clone()) != self.real { return Err(Error::MismatchJids( @@ -70,7 +71,7 @@ impl Occupant { } /// Remove a session from the occupant - pub fn remove_session(&mut self, presence: Presence) -> Result<(), Error> { + pub fn remove_session(&mut self, presence: PresenceFull) -> Result<(), Error> { let own_session = Session::try_from(presence)?; let len = self.sessions.len(); @@ -86,7 +87,7 @@ impl Occupant { } /// Update session presence - pub fn update_presence(&mut self, presence: Presence) -> Result<(), Error> { + pub fn update_presence(&mut self, presence: PresenceFull) -> Result<(), Error> { let own_session = Session::try_from(presence)?; for (i, session) in self.sessions.iter().enumerate() { @@ -142,38 +143,52 @@ mod tests { #[tokio::test] async fn test_occupant_update_presence() { - let presence_louise1 = Presence::new(PresenceType::None) - .with_from(LOUISE_FULL1.clone()) - .with_to(LOUISE_ROOM1_PART.clone()); - let presence_louise2 = Presence::new(PresenceType::None) - .with_from(LOUISE_FULL2.clone()) - .with_to(LOUISE_ROOM1_PART.clone()); + let presence_louise1 = PresenceFull::try_from( + Presence::new(PresenceType::None) + .with_from(LOUISE_FULL1.clone()) + .with_to(LOUISE_ROOM1_PART.clone()), + ) + .unwrap(); + let presence_louise2 = PresenceFull::try_from( + Presence::new(PresenceType::None) + .with_from(LOUISE_FULL2.clone()) + .with_to(LOUISE_ROOM1_PART.clone()), + ) + .unwrap(); let mut occupant = Occupant::new(presence_louise1).unwrap(); occupant.add_session(presence_louise2).unwrap(); - let presence1 = Presence::new(PresenceType::None) - .with_from(LOUISE_FULL1.clone()) - .with_to(ROOM1_BARE.clone()) - .with_show(PresenceShow::Away) - .with_payloads(vec![ - Muc::new().into(), - MucUser { - status: Vec::new(), - items: vec![MucItem::new(Affiliation::Owner, Role::Moderator)], - } - .into(), - ]); + let presence1 = PresenceFull::try_from( + Presence::new(PresenceType::None) + .with_from(LOUISE_FULL1.clone()) + .with_to(LOUISE_ROOM1_PART.clone()) + .with_show(PresenceShow::Away) + .with_payloads(vec![ + Muc::new().into(), + MucUser { + status: Vec::new(), + items: vec![MucItem::new(Affiliation::Owner, Role::Moderator)], + } + .into(), + ]), + ) + .unwrap(); + match occupant.update_presence(presence1.clone()) { Ok(()) => (), err => panic!("Err: {:?}", err), } + assert_eq!(occupant.sessions[0].presence, presence1); - let presence2 = Presence::new(PresenceType::None) - .with_from(LOUISE_FULL2.clone()) - .with_to(ROOM1_BARE.clone()) - .with_show(PresenceShow::Xa); + let presence2 = PresenceFull::try_from( + Presence::new(PresenceType::None) + .with_from(LOUISE_FULL2.clone()) + .with_to(LOUISE_ROOM1_PART.clone()) + .with_show(PresenceShow::Xa), + ) + .unwrap(); match occupant.update_presence(presence2.clone()) { Err(Error::SecondarySession(session)) if session.real() == &*LOUISE_FULL2 => (), @@ -187,9 +202,12 @@ mod tests { Session::try_from(presence2.clone()).unwrap() ); - let presence_leave_louise2 = Presence::new(PresenceType::Unavailable) - .with_from(LOUISE_FULL2.clone()) - .with_to(LOUISE_ROOM1_PART.clone()); + let presence_leave_louise2 = PresenceFull::try_from( + Presence::new(PresenceType::Unavailable) + .with_from(LOUISE_FULL2.clone()) + .with_to(LOUISE_ROOM1_PART.clone()), + ) + .unwrap(); occupant.remove_session(presence_leave_louise2).unwrap(); match occupant.update_presence(presence2) { diff --git a/src/room.rs b/src/room.rs index 2a1ae54..f9ae1b7 100644 --- a/src/room.rs +++ b/src/room.rs @@ -16,6 +16,7 @@ use crate::component::ComponentTrait; use crate::error::Error; use crate::occupant::Occupant; +use crate::presence::PresenceFull; use crate::session::{Nick, Session}; use std::collections::BTreeMap; @@ -69,7 +70,7 @@ impl Room { &self, component: &mut C, own_occupant: &Occupant, - presence: Presence, + presence: PresenceFull, mode: BroadcastPresence, ) -> Result<(), Error> { let leave = matches!(mode, BroadcastPresence::Leave); @@ -243,7 +244,7 @@ impl Room { pub async fn add_session( &mut self, component: &mut C, - presence: Presence, + presence: PresenceFull, ) -> Result<(), Error> { let new_session = Session::try_from(presence)?; let new_nick = new_session.participant().resource.clone(); @@ -310,7 +311,7 @@ impl Room { pub async fn update_presence( &mut self, component: &mut C, - presence: Presence, + presence: PresenceFull, ) -> Result<(), Error> { let session = Session::try_from(presence)?; @@ -334,7 +335,7 @@ impl Room { pub async fn remove_session( &mut self, component: &mut C, - presence: Presence, + presence: PresenceFull, ) -> Result<(), Error> { let session = Session::try_from(presence)?; // If occupant doesn't exist, ignore. @@ -425,17 +426,26 @@ mod tests { let realjid3 = FullJid::from_str("bar@qxx/foo").unwrap(); let participant3 = roomjid.clone().with_resource(String::from("nick3")); - let presence1 = Presence::new(PresenceType::None) - .with_from(realjid1.clone()) - .with_to(participant1.clone()); + let presence1 = PresenceFull::try_from( + Presence::new(PresenceType::None) + .with_from(realjid1.clone()) + .with_to(participant1.clone()), + ) + .unwrap(); - let presence2 = Presence::new(PresenceType::None) - .with_from(realjid2.clone()) - .with_to(participant2.clone()); + let presence2 = PresenceFull::try_from( + Presence::new(PresenceType::None) + .with_from(realjid2.clone()) + .with_to(participant2.clone()), + ) + .unwrap(); - let presence3 = Presence::new(PresenceType::None) - .with_from(realjid3.clone()) - .with_to(participant3.clone()); + let presence3 = PresenceFull::try_from( + Presence::new(PresenceType::None) + .with_from(realjid3.clone()) + .with_to(participant3.clone()), + ) + .unwrap(); let mut room = Room::new(roomjid.clone()); @@ -514,17 +524,26 @@ mod tests { let realjid3 = FullJid::from_str("bar@qxx/foo").unwrap(); let participant3 = roomjid.clone().with_resource(String::from("nick3")); - let presence1 = Presence::new(PresenceType::None) - .with_from(realjid1.clone()) - .with_to(participant1.clone()); + let presence1 = PresenceFull::try_from( + Presence::new(PresenceType::None) + .with_from(realjid1.clone()) + .with_to(participant1.clone()), + ) + .unwrap(); - let presence2 = Presence::new(PresenceType::None) - .with_from(realjid2.clone()) - .with_to(participant2.clone()); + let presence2 = PresenceFull::try_from( + Presence::new(PresenceType::None) + .with_from(realjid2.clone()) + .with_to(participant2.clone()), + ) + .unwrap(); - let presence3 = Presence::new(PresenceType::None) - .with_from(realjid3.clone()) - .with_to(participant3.clone()); + let presence3 = PresenceFull::try_from( + Presence::new(PresenceType::None) + .with_from(realjid3.clone()) + .with_to(participant3.clone()), + ) + .unwrap(); let mut room = Room::new(roomjid.clone()); @@ -586,17 +605,26 @@ mod tests { let realjid3 = FullJid::from_str("bar@qxx/foo").unwrap(); let participant3 = roomjid.clone().with_resource(String::from("nick3")); - let presence1 = Presence::new(PresenceType::None) - .with_from(realjid1.clone()) - .with_to(participant1.clone()); + let presence1 = PresenceFull::try_from( + Presence::new(PresenceType::None) + .with_from(realjid1.clone()) + .with_to(participant1.clone()), + ) + .unwrap(); - let presence2 = Presence::new(PresenceType::None) - .with_from(realjid2.clone()) - .with_to(participant2.clone()); + let presence2 = PresenceFull::try_from( + Presence::new(PresenceType::None) + .with_from(realjid2.clone()) + .with_to(participant2.clone()), + ) + .unwrap(); - let presence3 = Presence::new(PresenceType::None) - .with_from(realjid3.clone()) - .with_to(participant3.clone()); + let presence3 = PresenceFull::try_from( + Presence::new(PresenceType::None) + .with_from(realjid3.clone()) + .with_to(participant3.clone()), + ) + .unwrap(); let mut room = Room::new(roomjid.clone()); @@ -689,17 +717,26 @@ mod tests { #[tokio::test] async fn test_broadcast_presence_leave() { - let presence_louise = Presence::new(PresenceType::None) - .with_from(LOUISE_FULL1.clone()) - .with_to(LOUISE_ROOM1_PART.clone()); + let presence_louise = PresenceFull::try_from( + Presence::new(PresenceType::None) + .with_from(LOUISE_FULL1.clone()) + .with_to(LOUISE_ROOM1_PART.clone()), + ) + .unwrap(); - let presence_sugako = Presence::new(PresenceType::None) - .with_from(SUGAKO_FULL1.clone()) - .with_to(SUGAKO_ROOM1_PART.clone()); + let presence_sugako = PresenceFull::try_from( + Presence::new(PresenceType::None) + .with_from(SUGAKO_FULL1.clone()) + .with_to(SUGAKO_ROOM1_PART.clone()), + ) + .unwrap(); - let presence_rosa = Presence::new(PresenceType::None) - .with_from(ROSA_FULL1.clone()) - .with_to(ROSA_ROOM1_PART.clone()); + let presence_rosa = PresenceFull::try_from( + Presence::new(PresenceType::None) + .with_from(ROSA_FULL1.clone()) + .with_to(ROSA_ROOM1_PART.clone()), + ) + .unwrap(); let mut room = Room::new(ROOM1_BARE.clone()); @@ -756,9 +793,12 @@ mod tests { .into()]), ); - let presence_leave = Presence::new(PresenceType::Unavailable) - .with_from(ROSA_FULL1.clone()) - .with_to(ROSA_ROOM1_PART.clone()); + let presence_leave = PresenceFull::try_from( + Presence::new(PresenceType::Unavailable) + .with_from(ROSA_FULL1.clone()) + .with_to(ROSA_ROOM1_PART.clone()), + ) + .unwrap(); room.broadcast_presence( &mut component, diff --git a/src/session.rs b/src/session.rs index ad56022..323b92b 100644 --- a/src/session.rs +++ b/src/session.rs @@ -14,6 +14,7 @@ // along with this program. If not, see . use crate::error::Error; +use crate::presence::PresenceFull; use xmpp_parsers::{presence::Presence, FullJid, Jid}; @@ -22,12 +23,12 @@ pub type Nick = String; /// An occupant session #[derive(Debug, Clone)] pub struct Session { - pub presence: Presence, + pub presence: PresenceFull, } impl Session { /// Ensure presence doesn't contain payloads that would impersonate us - fn filter_presence(presence: Presence) -> Presence { + fn filter_presence(presence: PresenceFull) -> PresenceFull { presence } @@ -48,7 +49,16 @@ impl Session { impl PartialEq for Session { fn eq(&self, other: &Session) -> bool { - self.real() == other.real() && self.participant() == other.participant() + self.real() == other.real() // && self.participant() == other.participant() + } +} + +impl TryFrom for Session { + type Error = Error; + + fn try_from(presence: PresenceFull) -> Result { + let presence = Session::filter_presence(presence); + Ok(Session { presence }) } } @@ -56,7 +66,9 @@ impl TryFrom for Session { type Error = Error; fn try_from(presence: Presence) -> Result { - let presence = Session::filter_presence(presence); - Ok(Session { presence }) + let presence: PresenceFull = PresenceFull::try_from(presence)?; + Ok(Session { + presence: Session::filter_presence(presence), + }) } } diff --git a/src/tests/templates.rs b/src/tests/templates.rs index e53d142..44c95ab 100644 --- a/src/tests/templates.rs +++ b/src/tests/templates.rs @@ -14,6 +14,7 @@ // along with this program. If not, see . use crate::occupant::Occupant; +use crate::presence::PresenceFull; use crate::room::Room; use crate::session::Nick; use std::str::FromStr; @@ -79,7 +80,7 @@ pub fn one_participant_room(roomjid: BareJid) -> Room { .with_to(LOUISE_ROOM1_PART.clone()); room.occupants.insert( String::from(LOUISE_NICK), - Occupant::new(presence_louise).unwrap(), + Occupant::new(PresenceFull::try_from(presence_louise).unwrap()).unwrap(), ); room } @@ -94,11 +95,11 @@ pub fn two_participant_room(roomjid: BareJid) -> Room { .with_to(SUGAKO_ROOM1_PART.clone()); room.occupants.insert( String::from(LOUISE_NICK), - Occupant::new(presence_louise).unwrap(), + Occupant::new(PresenceFull::try_from(presence_louise).unwrap()).unwrap(), ); room.occupants.insert( String::from(SUGAKO_NICK), - Occupant::new(presence_sugako).unwrap(), + Occupant::new(PresenceFull::try_from(presence_sugako).unwrap()).unwrap(), ); room } @@ -111,9 +112,12 @@ pub async fn new_room>(roomjid: BareJid, sessions: Vec<(FullJid, N let nick: Nick = nick.into(); let participant = roomjid.clone().with_resource(nick.clone()); - let presence = Presence::new(PresenceType::None) - .with_to(participant) - .with_from(session); + let presence = PresenceFull::try_from( + Presence::new(PresenceType::None) + .with_to(participant) + .with_from(session), + ) + .unwrap(); match room.occupants.get_mut(&nick) { Some(occupant) => occupant.add_session(presence).unwrap(),