diff --git a/src/error.rs b/src/error.rs index fc8bae7..84db214 100644 --- a/src/error.rs +++ b/src/error.rs @@ -36,8 +36,10 @@ pub enum Error { /// Raised whenever an operation is applied to a session which isn't the primary session, used /// for Multi-Session Nick support. SecondarySession(Session), - /// Raised when a JID was supposed to be present - MissingJid, + /// The origin (from) JID isn't of the expected for (bare or full) + InvalidOriginJid, + /// The destination (to) JID isn't of the expected for (bare or full) + InvalidDestinationJid, /// Unhandled Iq with error description UnhandledIq(String), /// Jid Parse errors @@ -59,7 +61,8 @@ impl fmt::Display for Error { Error::SessionAlreadyExists(err) => write!(f, "Session already exist: {:?}", err), Error::ParticipantNotFound(err) => write!(f, "Participant not found: {}", err), Error::SecondarySession(err) => write!(f, "Secondary session: {:?}", err), - Error::MissingJid => write!(f, "Missing JID"), + Error::InvalidOriginJid => write!(f, "Invalid origin JID"), + Error::InvalidDestinationJid => write!(f, "Invalid destination JID"), Error::UnhandledIq(err) => write!(f, "Unhandled Iq: {:?}", err), Error::Jid(err) => write!(f, "Jid Parse error: {}", err), Error::Xmpp(err) => write!(f, "XMPP error: {}", err), diff --git a/src/occupant.rs b/src/occupant.rs index 0dc14ba..b744930 100644 --- a/src/occupant.rs +++ b/src/occupant.rs @@ -33,11 +33,12 @@ pub struct Occupant { impl Occupant { /// New occupant pub fn new(presence: Presence) -> Result { + let participant = presence.to.clone().map(FullJid::try_from).unwrap().unwrap(); let session = Session::try_from(presence)?; Ok(Occupant { - real: BareJid::from(session.real.clone()), - participant: session.participant.clone(), - nick: session.participant.resource.clone(), + real: BareJid::from(session.real().clone()), + nick: participant.resource.clone(), + participant: participant, sessions: vec![session], }) } @@ -51,15 +52,15 @@ impl Occupant { /// Add a new session to the occupant pub fn add_session(&mut self, presence: Presence) -> Result<(), Error> { let new_session = Session::try_from(presence)?; - if BareJid::from(new_session.real.clone()) != self.real { + if BareJid::from(new_session.real().clone()) != self.real { return Err(Error::MismatchJids( Jid::from(self.real.clone()), - Jid::from(new_session.real), + Jid::from(new_session.real().clone()), )); } for session in &self.sessions { - if &new_session.real == &session.real { + if new_session.real() == session.real() { return Err(Error::SessionAlreadyExists(new_session)); } } @@ -74,7 +75,7 @@ impl Occupant { let len = self.sessions.len(); self.sessions - .retain(|session| session.real != own_session.real); + .retain(|session| session.real() != own_session.real()); // An item has been removed if len != self.sessions.len() { @@ -86,7 +87,7 @@ impl Occupant { /// Update session presence pub fn update_presence(&mut self, presence: Presence) -> Result<(), Error> { - let own_session = Session::with_nick(presence, self.participant.resource.clone())?; + let own_session = Session::try_from(presence)?; for (i, session) in self.sessions.iter().enumerate() { if &own_session == session { @@ -175,7 +176,7 @@ mod tests { .with_show(PresenceShow::Xa); match occupant.update_presence(presence2.clone()) { - Err(Error::SecondarySession(session)) if session.real == *LOUISE_FULL2 => (), + Err(Error::SecondarySession(session)) if session.real() == &*LOUISE_FULL2 => (), err => panic!( "Should return Error::SecondarySession(Session {{ {:?} }}), returned: {:?}", *LOUISE_FULL2, err, @@ -183,7 +184,7 @@ mod tests { } assert_eq!( occupant.sessions[1], - Session::with_nick(presence2.clone(), LOUISE_NICK.clone()).unwrap() + Session::try_from(presence2.clone()).unwrap() ); let presence_leave_louise2 = Presence::new(PresenceType::Unavailable) @@ -192,7 +193,7 @@ mod tests { occupant.remove_session(presence_leave_louise2).unwrap(); match occupant.update_presence(presence2) { - Err(Error::NonexistantSession(session)) if session.real == *LOUISE_FULL2 => (), + Err(Error::NonexistantSession(session)) if session.real() == &*LOUISE_FULL2 => (), err => panic!( "Should return Error::SecondarySession(Session {{ {:?} }}), returned: {:?}", *LOUISE_FULL2, err, diff --git a/src/room.rs b/src/room.rs index 1ba837e..2a1ae54 100644 --- a/src/room.rs +++ b/src/room.rs @@ -85,7 +85,7 @@ impl Room { } else { PresenceType::None }) - .with_to(Jid::Full(own_session.real.clone())) + .with_to(Jid::Full(own_session.real().clone())) .with_payloads(vec![MucUser { status: Vec::new(), items: vec![MucItem::new(Affiliation::Owner, Role::Moderator)], @@ -98,7 +98,7 @@ impl Room { } else { PresenceType::None }) - .with_from(Jid::Full(own_session.participant.clone())) + .with_from(Jid::Full(own_occupant.participant.clone())) .with_payloads(vec![MucUser { status: Vec::new(), items: vec![MucItem::new( @@ -124,7 +124,7 @@ impl Room { // Send presence from participant to others. for session in other.iter() { // Skip sending if it's us. - if session.real == own_session.real { + if session.real() == own_session.real() { continue; } // If own_session is leaving, and it is not the primary @@ -135,7 +135,7 @@ impl Room { let presence = presence_to_old .clone() - .with_to(Jid::Full(session.real.clone())); + .with_to(Jid::Full(session.real().clone())); component.send_stanza(presence).await?; } } @@ -151,7 +151,7 @@ impl Room { } else { Role::Moderator }, - jid: Some(session.real.clone()), + jid: Some(session.real().clone()), nick: None, actor: None, continue_: None, @@ -174,7 +174,7 @@ impl Room { } let presence = session_presence .clone() - .with_to(Jid::Full(session.real.clone())) + .with_to(Jid::Full(session.real().clone())) .with_payloads(vec![MucUser { status: vec![], items: self_items.clone(), @@ -192,7 +192,7 @@ impl Room { PresenceType::None }) .with_from(Jid::Full(own_occupant.participant.clone())) - .with_to(own_session.real.clone()) + .with_to(own_session.real().clone()) .with_payloads(vec![MucUser { status: if leave { vec![MucStatus::SelfPresence] @@ -222,7 +222,7 @@ impl Room { self.subject = Some((subject, setter, stamp)); } - let mut subject = Message::new(Some(Jid::Full(session.real))); + let mut subject = Message::new(Some(Jid::Full(session.real().clone()))); subject.from = Some(Jid::Full( self.subject.as_ref().unwrap().1.participant.clone(), )); @@ -246,8 +246,8 @@ impl Room { presence: Presence, ) -> Result<(), Error> { let new_session = Session::try_from(presence)?; - let new_nick = new_session.participant.resource.clone(); - let realjid = new_session.real.clone(); + let new_nick = new_session.participant().resource.clone(); + let realjid = new_session.real().clone(); // Ensure nick isn't already assigned self.occupants.iter().try_for_each(|(nick, occupant)| { @@ -338,7 +338,7 @@ impl Room { ) -> Result<(), Error> { let session = Session::try_from(presence)?; // If occupant doesn't exist, ignore. - if let Some(mut occupant) = self.occupants.remove(&session.participant.resource) { + if let Some(mut occupant) = self.occupants.remove(&session.participant().resource) { self.broadcast_presence( component, &occupant, @@ -347,11 +347,11 @@ impl Room { ) .await?; - occupant.remove_session(session.presence)?; + occupant.remove_session(session.presence.clone())?; if occupant.iter().len() > 0 { let _ = self .occupants - .insert(session.participant.resource.clone(), occupant); + .insert(session.participant().resource.clone(), occupant); } } else { // TODO: Error @@ -363,15 +363,15 @@ impl Room { /// Fetch the occupant associated with the provided nick and ensure the session is part of /// it. pub fn get_occupant(&self, session: &Session) -> Result<&Occupant, Error> { - if let Some(occupant) = self.occupants.get(&session.participant.resource) { - if occupant.contains(&session.real) { + if let Some(occupant) = self.occupants.get(&session.participant().resource) { + if occupant.contains(session.real()) { Ok(occupant) } else { Err(Error::NonexistantSession(session.clone())) } } else { Err(Error::ParticipantNotFound( - session.participant.resource.clone(), + session.participant().resource.clone(), )) } } @@ -379,15 +379,15 @@ impl Room { /// Fetch a mutable reference of the occupant associated with the provided nick and ensure the /// session is part of it. pub fn get_mut_occupant(&mut self, session: &Session) -> Result<&mut Occupant, Error> { - if let Some(occupant) = self.occupants.get_mut(&session.participant.resource) { - if occupant.contains(&session.real) { + if let Some(occupant) = self.occupants.get_mut(&session.participant().resource) { + if occupant.contains(session.real()) { Ok(occupant) } else { Err(Error::NonexistantSession(session.clone())) } } else { Err(Error::ParticipantNotFound( - session.participant.resource.clone(), + session.participant().resource.clone(), )) } } diff --git a/src/session.rs b/src/session.rs index 018efd2..ad56022 100644 --- a/src/session.rs +++ b/src/session.rs @@ -15,7 +15,7 @@ use crate::error::Error; -use xmpp_parsers::{presence::Presence, BareJid, FullJid}; +use xmpp_parsers::{presence::Presence, FullJid, Jid}; pub type Nick = String; @@ -23,8 +23,6 @@ pub type Nick = String; #[derive(Debug, Clone)] pub struct Session { pub presence: Presence, - pub real: FullJid, - pub participant: FullJid, } impl Session { @@ -33,29 +31,24 @@ impl Session { presence } - /// Instanciate a Session from a presence which is adressed to the room JID. - pub fn with_nick>(presence: Presence, nick: N) -> Result { - let presence = Session::filter_presence(presence); - Ok(Session { - real: presence - .from - .clone() - .map(FullJid::try_from) - .ok_or(Error::MissingJid)??, - participant: presence - .to - .clone() - .map(BareJid::from) - .ok_or(Error::MissingJid)? - .with_resource(nick.into()), - presence, - }) + pub fn real(&self) -> &FullJid { + match &self.presence.from { + Some(Jid::Full(full)) => full, + _ => unreachable!(), + } + } + + pub fn participant(&self) -> &FullJid { + match &self.presence.to { + Some(Jid::Full(full)) => full, + _ => unreachable!(), + } } } 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() } } @@ -64,18 +57,6 @@ impl TryFrom for Session { fn try_from(presence: Presence) -> Result { let presence = Session::filter_presence(presence); - Ok(Session { - real: presence - .from - .clone() - .map(FullJid::try_from) - .ok_or(Error::MissingJid)??, - participant: presence - .to - .clone() - .map(FullJid::try_from) - .ok_or(Error::MissingJid)??, - presence, - }) + Ok(Session { presence }) } }